pacman::p_load(readxl,reshape,survival,survminer,ggplot2,cowplot,dplyr,My.stepwise,haven,tidyr,knitr,lubridate,naniar,table1, Hmisc,skimr,psych,lavaan)

1. Path Analysis

Structural Equation Model (SEM) si a general analytic framework that include t-test, ANOVA, MANOVA, multiple regression, path analysis,factor analysis, growth trajectories.

1.0 Overall Concepts

  1. Specification

Predictor, Outcomes, Mediators, Factors. Use Path Diagrams for specification

  1. Identification
    • the t-rule: \(k = \frac{(p+q)(p+q+1)}{2}+(p+q)\), number of parameters must \(\le\)k. Necessay but not sufficient
    • the Null B rule: \(\mathbf{y_i= \alpha+ By_i+ \Gamma x_i+ \zeta_i}\), when B=0, there is no relations among the DVs. Sufficient
    • the recursive rule: no feedback or bi-directional effects, no correlated residuals. Sufficient but not necessary.
    • the common sense rule

possible to obtain all model parameter estimates?

Model-Implied Moments: Model is a set of parameters. Population Moments include means and covariance. Model-Implied Moments is moment matrix implied by the model, which is similar to y and \(\hat{y}\). can each parameter be uniquely expressed using observed information? Extent to which there is sufficient known information to infer unknown values. Over-identified is observed > estimated. population moments are \(\Sigma\) and \(\mu\). Sample moments are S and m. population model-implied moments are \(\Sigma(\theta)\) and \(\mu(\theta)\)

  1. Estimation

How to obtain best estimates. ML is asymptotically unbiased,consistent, and maximally efficient.

  1. Evaluation
    • R square: variance explained by the model
    • Chi-Square Test Statistics: compare with the saturated model which impose no restrictions on means or covariances. non-significant means the tested model is good. Poorly fitting model can be accepted because there is insufficient power to detect the misspecification. Used for nested model comparison.
    • Relative Goodness of Fit Indices:TLI,CFI, IFI >0.95 is good. baseline model, all mean and variance and no covariance. hypothesized model is the tested model.
    • Absolute Goodness of Fit Indices: RMSEA (\(\le\) 0.05 is excellent; \(\le\) 0.08 moderate fit; >1.0 is poor). Standardized Root Mean Square Residual SRMR (\(\le\) .08 is good, not penalized for the number of model parameters, so tends to be better for less restricted models).

How well does the model fit the data. Relative fit of competing models can be compared using likelihood ratio tests (chi-square difference tests). Regressions are just-identified, uses the same number of parameters to exactly reproduce the observed moments. So the model necessarily fits perfectly and is said to be saturated. Most SEMs, are over-identified, resulting testable restrictions on model-implied moments.

  1. Potential re-specification
    • Modification Indices (MIs): expected change (based on model derivatives not actual likelihood ratio tests. but very close estimates). Calculated for every parameter that is restricted. Take one at a time, entiredly data driven

Can the model be improved? How are modifications identified

  1. Interpretation

Which effects are significant? Which are substan

  • Disturbance: unexplained variance of an endogenous variable. the part that is unrelated to the predictors

1.1 Dataset Description: Deviant Peer Addiliations

read Deviant Peer Addiliations dataset The header argument of the read.table function is set to FALSE here to indicate that there are no variable names at the top of the data file.

afdp <- read.table("data/afdp.dat", header = FALSE ,col.names =c("id","coa","age","gen","stress","emotion","negaff","peer"))
psych::describe(afdp)

peer adolescent report on peer substance use and peer tolerance of use

coa parent report of alcoholism diagnosis where 0=non-alcoholic and 1=alcoholic

gen gender 0=girl 1=boy

age age measured in years at assessment

stress self report measure of uncontrollable negative life stressful events

emotion self report measure of temperamental emotional expressiveness

negaff self report measure of depression and anxiety

1.2 Simple Regression

peer = α + γ coa + ζ

First, we need to create what’s called a model syntax object.Then fit the model using the sem function, placing the results into the data object fit. Note that we include the meanstructure argument with the sem function so that we will obtain an estimate of the regression intercept.

model.1 <- 'peer ~ coa'
summary(sem(model.1, data=afdp, meanstructure=TRUE),standardized=TRUE,rsquare=TRUE)
lavaan 0.6-12 ended normally after 9 iterations

  Estimator                                         ML
  Optimization method                           NLMINB
  Number of model parameters                         3

  Number of observations                           316

Model Test User Model:
                                                      
  Test statistic                                 0.000
  Degrees of freedom                                 0

Parameter Estimates:

  Standard errors                             Standard
  Information                                 Expected
  Information saturated (h1) model          Structured

Regressions:
                   Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
  peer ~                                                                
    coa               0.176    0.060    2.956    0.003    0.176    0.164

Intercepts:
                   Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
   .peer              0.298    0.043    6.884    0.000    0.298    0.554

Variances:
                   Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
   .peer              0.280    0.022   12.570    0.000    0.280    0.973

R-Square:
                   Estimate
    peer              0.027

we are using ML (maximum likelihood) estimation with the nlminb optimizer (this is a built-in optimizer in R for finding the minimum of a function).

It is worth pausing here to note that lavaan counts parameters differently than we described in lecture. For this model, we would normally count five parameters, the mean and variance of COA, the intercept and slope of the regression of Peer on COA, and the residual variance of Peer. But lavaan does not count the mean or variance of the predictor, COA, as parameters of the model. Nor does it count covariances among predictors (though there are no such covariances in the current model) as free parameters. Fortunately, lavaan also does not count these parameters when determining the number of observed moments, so the degrees of freedom for the test statistic work out regardless (e.g., here it neither counts the mean and variance of COA as observed moments nor does it count them as estimated moments, leaving a net difference of zero when calculating the degrees of freedom).

This output also provides some information about model fit. Multiple regression models are just identified (i.e., every piece of information provided by the sample is ‘used up’ to estimate model parameters so that no degrees of freedom remain). Therefore, the model fits the data perfectly and it is not worthwhile to interpret the test statistic (this and other fit indices will be discussed in later sections).

The output is subdivided into three parts, regressions, intercepts, and variances. In the Regressions section, the peer ~ coa coefficient is the slope parameter estimate γ . In the ˆ Intercepts section, the coefficient listed for .peer is the intercept α . Finally, in the Variances section, the coefficient listed for .peer is the represents represents ψ , the estimated variance of ζ i (i.e., residual variance). The Estimate column lists is the ML point estimate of each parameter. The Std.Err column gives the standard error for each estimate (where these are computed using the expected information matrix, as noted above). Next, the z-value column reports the Wald z-statistic for the null hypothesis test that the parameter is significantly different from zero in the population, and the P(>|z|) column reports the p-value associated with this z-statistic.

Here, we see that the average non-COA has a score of .298 on peer and the average COA has a score that is .176 units higher than non-COAs on peer (.298 + .176 = .474). Both the intercept and slope are significantly different from zero. Finally, the variance in deviant peer association that is not explained by COA status is .280. This indicates that, although COA status is a significant predictor of peer, COA status does not fully account for affiliation with peers.

Because peer is not on an intrinsically meaningful scale, we cannot easily interpret the differences among the regression parameters or residual variances. To better interpret these results, we can request standardized estimates. Within lavaan, several methods of standardization are available within the summary function. The first type, obtained by including standardized=TRUE, is the typical fully standardized solution. In this case, both the independent and dependent variables are standardized to have a variance of 1 (note that lavaan does not, however, also make the means 0, as one might expect).

The Std.lv column refers to a solution in which only the latent variables are standardized and not the observed variables. Since the current model contains no latent variables, this is of little use here. The Std.all column contains the fully standardized estimates of interest, in which all variables (observed and latent) are standardized to have a variance of one. Thus, we say that a one standard deviation increase in COA status is associated with a .164 standard deviation increase in deviant peer associations.

It may be more useful to retain the original scaling of COA while standardizing peer. If we include std.nox=TRUE in the summary function, as shown below, we will obtain estimates in which the latent variables and endogenous observed variables are standardized but the exogenous observed variables are left in their raw scale. These are commonly known as partially standardized estimates.

Finally, we can also calculate how much variance is explained in peer by coa by requesting that lavaan output the r-squared statistic. R-Square is the estimated proportion of variance in peer that is accounted for by the models (i.e., COA, the only predictor included in this model). We have explained less than 3% of the total variance in peer with the COA predictor. Note, however, that measured variable regression models assume that no measurement error is present. If measurement error is present, the estimated relationship among the variables in the model may be attenuated and the R 2 value will also be underestimated.

1.3 Multiple Regression

peer = α + γ1coa + γ 2gen + γ 3age + ζ

we have specified that peer is regression on coa, gen, and age. Note that, again, we use the regression operator ~ to indicate the regression. Now that our model includes multiple predictors, we use the + operator in between each predictor.

summary( sem('peer ~ coa + gen + age', data=afdp, meanstructure=TRUE), std.nox=TRUE, rsquare=TRUE)
lavaan 0.6-12 ended normally after 19 iterations

  Estimator                                         ML
  Optimization method                           NLMINB
  Number of model parameters                         5

  Number of observations                           316

Model Test User Model:
                                                      
  Test statistic                                 0.000
  Degrees of freedom                                 0

Parameter Estimates:

  Standard errors                             Standard
  Information                                 Expected
  Information saturated (h1) model          Structured

Regressions:
                   Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.nox
  peer ~                                                                
    coa               0.210    0.054    3.858    0.000    0.210    0.391
    gen              -0.048    0.055   -0.877    0.381   -0.048   -0.089
    age               0.151    0.019    7.993    0.000    0.151    0.281

Intercepts:
                   Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.nox
   .peer             -1.610    0.250   -6.453    0.000   -1.610   -2.999

Variances:
                   Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.nox
   .peer              0.232    0.018   12.570    0.000    0.232    0.804

R-Square:
                   Estimate
    peer              0.196

We see that gen is not a significant predictor of peer when COA and age are also included in the model (p = .381). However, age is significantly related with peer such that older adolescents are more likely to associate with deviant peers. We estimate that a one-year increase in age is associated with a .151-increase in deviant peer association ratings. COA remains a significant predictor of peer, and the regression parameter estimate (i.e., it has increased from .18 to .21) has not changed much from the single-predictor model to the multiple-predictor model relative to its standard error (0.06). The stability of this coefficient reflects the fact that COA is not highly correlated with gen or age.

To better interpret these results, and to get a sense for the relative contribution of each predictor, we requested the partially standardized solution. We prefer this method of standardization for this example because all three predictors have natural scales. As can be seen in the Std.nox column of output, after controlling for age and gender, COAs affiliate with deviant peers about .391 standard deviation units more than non-COAs. Each additional year of age is associated with a .281 standard deviation increase in self-reported affiliation with deviant peers.

From the R-square output, we can see that the multiple predictor regression model explains more of the variance in peer than the single predictor model. Age and gender account for an additional 17% of the variance in peer, over and above COA status. Still, approximately 80% of the variance in peer remains unexplained by the variables in our model.

1.4 Path Analysis

1.4.1 Original Model

Theory dictates that alcoholic parents increase the number of stressful life events that their children experience, leading to an increase in child negative affect. Further, children of alcoholics are hypothesized to have higher levels of emotionality, leading to more negative affect. Negative affect is thought to be related to higher rates of affiliation从属,加盟 with deviant peers. Stressful life events and emotionality should covary, but we hypothesize no directional relation among these variables. We allow age and gen to predict stress and emotion, and we allow all exogenous characteristics (coa, gen, and age) to covary.

As a default, lavaan allows all exogenous variables to covary but it fixes the residual covariances among endogenous variables to zero. The residual terms of stress and emotion are freed to covary within the section of the code marked #covariances. To designate a covariance (or variance) we use the ~~ operator. Thus, stress ~~ emotion tells lavaan to include a residual covariance for stress and emotion.

The final three lines request the model-implied covariance matrix (fitted(fit)) and the raw and standardized residual matrices (resid(fit, type=“raw”) and resid(fit, type=“normalized”), respectively). These residuals represent the differences between the observed covariance matrix and the matrix that is implied by the structure of the model.

pathmodel.1 <- '
              #regressions
              stress ~ coa + gen + age
              emotion ~ coa + gen + age
              negaff ~ stress + emotion
              peer ~ negaff

              #covariances
              stress ~~ emotion              
              '
fit <- sem(pathmodel.1, data=afdp, meanstructure=TRUE)
summary(fit, standardized=TRUE, rsquare=TRUE)
lavaan 0.6-12 ended normally after 40 iterations

  Estimator                                         ML
  Optimization method                           NLMINB
  Number of model parameters                        18

  Number of observations                           316

Model Test User Model:
                                                      
  Test statistic                                81.173
  Degrees of freedom                                 8
  P-value (Chi-square)                           0.000

Parameter Estimates:

  Standard errors                             Standard
  Information                                 Expected
  Information saturated (h1) model          Structured

Regressions:
                   Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
  stress ~                                                              
    coa               0.451    0.072    6.223    0.000    0.451    0.331
    gen              -0.016    0.073   -0.215    0.830   -0.016   -0.011
    age               0.002    0.025    0.078    0.938    0.002    0.004
  emotion ~                                                             
    coa               0.110    0.056    1.963    0.050    0.110    0.110
    gen              -0.048    0.056   -0.843    0.399   -0.048   -0.047
    age              -0.027    0.019   -1.374    0.170   -0.027   -0.077
  negaff ~                                                              
    stress            0.246    0.078    3.134    0.002    0.246    0.175
    emotion           0.553    0.106    5.206    0.000    0.553    0.290
  peer ~                                                                
    negaff            0.176    0.030    5.892    0.000    0.176    0.315

Covariances:
                   Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
 .stress ~~                                                             
   .emotion           0.112    0.019    5.896    0.000    0.112    0.352

Intercepts:
                   Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
   .stress            0.687    0.333    2.066    0.039    0.687    1.010
   .emotion           2.341    0.258    9.088    0.000    2.341    4.663
   .negaff            1.527    0.207    7.373    0.000    1.527    1.594
   .peer             -0.118    0.091   -1.298    0.194   -0.118   -0.220

Variances:
                   Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
   .stress            0.412    0.033   12.570    0.000    0.412    0.890
   .emotion           0.247    0.020   12.570    0.000    0.247    0.979
   .negaff            0.778    0.062   12.570    0.000    0.778    0.848
   .peer              0.260    0.021   12.570    0.000    0.260    0.901

R-Square:
                   Estimate
    stress            0.110
    emotion           0.021
    negaff            0.152
    peer              0.099

We report fully standardized effects (from Std.all column generated by the first summary function call) except for coa, gen, and age, for which we report partially standardized effects (from Std.nox column generated by the second summary function call). Recall that only the outcome variables are standardized in computing the partially standardized effects, which makes them particularly useful for examining the effects of coding variables (e.g., coa and gen) or predictors with natural metrics (e.g., age).

These partially standardized parameter estimates represent the expected change in standard deviation units in y given a one unit increase in x. By comparison, the fully standardized estimates are computed by standardizing both the predictors and the outcome variables so that parameter estimates represent the expected change in standard deviation units in y given a one standard deviation increase in x. These are most useful for interpreting effects when neither predictors nor outcomes have natural scales and when gauging relative effect sizes across predictors on different scales. For covariance parameters, fully standardized estimates can be interpreted as correlations.

From the R-Square section of output, we can also see that only a modest amount of the total variance in any of these variables has been explained by the model.

resid(fit, type="normalized")
$type
[1] "normalized"

$cov
        stress emotin negaff peer   coa    gen    age   
stress   0.000                                          
emotion  0.000  0.000                                   
negaff   0.000  0.000  0.000                            
peer     2.657  0.395  0.000  0.000                     
coa      0.000  0.000 -0.163  2.685  0.000              
gen      0.000  0.000 -1.580 -1.548  0.000  0.000       
age      0.000  0.000  3.229  8.015  0.000  0.000  0.000

$mean
 stress emotion  negaff    peer     coa     gen     age 
      0       0       0       0       0       0       0 

The normalized residuals are rescaled to follow a standard normal distribution and values exceeding plus or minus two are often taken as potentially meaningful in magnitude. The normalized residuals for this model suggest that the hypothesized structure is doing a poor job in reproducing the observed covariances between several variables, most notably between age and peer, between age and negaff, and between stress and peer. We will explore methods for more formally assessing overall model fit in the next chapter.

1.4.2 Evaluation and re-specification

We obtain measures of fit, appropriately enough, by including fit.measures=TRUE

summary(fit, fit.measures=TRUE)
lavaan 0.6-12 ended normally after 40 iterations

  Estimator                                         ML
  Optimization method                           NLMINB
  Number of model parameters                        18

  Number of observations                           316

Model Test User Model:
                                                      
  Test statistic                                81.173
  Degrees of freedom                                 8
  P-value (Chi-square)                           0.000

Model Test Baseline Model:

  Test statistic                               251.027
  Degrees of freedom                                18
  P-value                                        0.000

User Model versus Baseline Model:

  Comparative Fit Index (CFI)                    0.686
  Tucker-Lewis Index (TLI)                       0.293

Loglikelihood and Information Criteria:

  Loglikelihood user model (H0)              -1158.938
  Loglikelihood unrestricted model (H1)      -1118.351
                                                      
  Akaike (AIC)                                2353.875
  Bayesian (BIC)                              2421.479
  Sample-size adjusted Bayesian (BIC)         2364.387

Root Mean Square Error of Approximation:

  RMSEA                                          0.170
  90 Percent confidence interval - lower         0.138
  90 Percent confidence interval - upper         0.205
  P-value RMSEA <= 0.05                          0.000

Standardized Root Mean Square Residual:

  SRMR                                           0.085

Parameter Estimates:

  Standard errors                             Standard
  Information                                 Expected
  Information saturated (h1) model          Structured

Regressions:
                   Estimate  Std.Err  z-value  P(>|z|)
  stress ~                                            
    coa               0.451    0.072    6.223    0.000
    gen              -0.016    0.073   -0.215    0.830
    age               0.002    0.025    0.078    0.938
  emotion ~                                           
    coa               0.110    0.056    1.963    0.050
    gen              -0.048    0.056   -0.843    0.399
    age              -0.027    0.019   -1.374    0.170
  negaff ~                                            
    stress            0.246    0.078    3.134    0.002
    emotion           0.553    0.106    5.206    0.000
  peer ~                                              
    negaff            0.176    0.030    5.892    0.000

Covariances:
                   Estimate  Std.Err  z-value  P(>|z|)
 .stress ~~                                           
   .emotion           0.112    0.019    5.896    0.000

Intercepts:
                   Estimate  Std.Err  z-value  P(>|z|)
   .stress            0.687    0.333    2.066    0.039
   .emotion           2.341    0.258    9.088    0.000
   .negaff            1.527    0.207    7.373    0.000
   .peer             -0.118    0.091   -1.298    0.194

Variances:
                   Estimate  Std.Err  z-value  P(>|z|)
   .stress            0.412    0.033   12.570    0.000
   .emotion           0.247    0.020   12.570    0.000
   .negaff            0.778    0.062   12.570    0.000
   .peer              0.260    0.021   12.570    0.000

We can request that lavaan suggest changes to our model based on the expected change in model chi-square if a fixed parameter were freed; these are the modification indices (MIs). We can obtain MIs with the modindices function. The sort. argument is set to TRUE so that lavaan will present the largest MIs first. Additionally, the minimum.value argument is set to suppress printing of any MIs less than 10.

modindices(fit, sort.=TRUE, minimum.value=10)

Here, lhs stands for “on the left-hand side of the operator” and rhs stands for “on the righthand side of the operator.” The operator, denoted op, for these parameters is ~, indicating these are regression slopes. mi denotes the expected improvement in the model chi square test statistic if the modification is accepted. epc denotes “expected parameter change (EPC)” and gives the expected parameter value if the modification is implemented (since it is changing from zero). sepc.lv re-scales the EPC by standardizing any latent variables in the model, sepc.all re-scales the EPC by standardizing all variables (observed and latent), and sepc.nox re-scales the EPC by standardizing all variables except exogenous predictors. Here, sepc.lv is equivalent to the EPC because there are no latent variables in the model. It can be helpful to rely on standardized EPC values in order to get a sense of the relative magnitude of each potential modification.

Final Model

pathmodel.5 <-'
              #regressions
              stress ~ coa + gen + age
              emotion ~ coa + gen + age
              negaff ~ stress + emotion + age
              peer ~ negaff + age + coa

              #covariances
              stress ~~ emotion              
              '
fit.5 <- sem(pathmodel.5, data=afdp, meanstructure=TRUE)
summary(fit.5, fit.measures=TRUE)
1.4.3 Mediation Test

Mediator explains why or how one variable exerts an effect on another. Indirect effect point estimate is product of coefficients in chain. the CI is calculated by delta method and bootstrapping.

Significant links in a mediational pathway are not sufficient to infer mediation. In order to formally test the full mediation effect, we need an inferential test of the entire specific indirect effect in question. Here, we want to know whether the specific mediational pathway of COA status on deviant peer affiliation via stressful events and negative affect is statistically significant, whether the specific mediational effect of coa on peer via emotionality and negative affect is significant, and whether the overall indirect effect of coa on peer is significant. Finally, we would like to have an estimate of the total effect of coa on peer considering both direct and indirect pathways.

we’ve added parameter labels for the paths involved in the direct and indirect effects of coa on peer. For instance, in the line stress ~ c_s*coa + gen + age, we have supplied the label c_s for the effect of coa on stress. Likewise, the other paths involved in computing the effects of interest have also been labeled. To help keep track of things, our labels consist of the first letter of the predictor, an underscore, and first letter of outcome, but any labels are fine. We can now refer to these labels when defining direct, indirect, and total effects.

Following the core model specification, we have new lines to define the direct, specific indirect, total indirect, and total effects. This is done using the “define” operator :=. For instance, ind_s := c_ss_nn_p requests that lavvan compute the quantity ind_s as the product of the three paths previously labeled c_s, s_n, and n_p.

effects.5 <-'
            #regressions
            stress ~ c_s*coa + gen + age
            emotion ~ c_e*coa + gen + age
            negaff ~ s_n*stress + e_n*emotion + age
            peer ~ n_p*negaff + age + c_p*coa 

            #covariances
            stress ~~ emotion         

            #direct effect
            dir := c_p

            #specific indirect effects
            ind_s := c_s*s_n*n_p
            ind_e := c_e*e_n*n_p

            #total indirect effect
            tot_ind := c_s*s_n*n_p + c_e*e_n*n_p

            #total effect
            tot := c_s*s_n*n_p + c_e*e_n*n_p + c_p
            '
set.seed(62973)
fit.5b <- sem(effects.5, data=afdp, meanstructure=TRUE, se="bootstrap", bootstrap=1000)

Note that we have used the set.seed function to set the random number seed for selecting the bootstrapped samples so that we can reproduce exactly these same results each time we run the script.

Then, in the sem function, we specified se=“bootstrap”, bootstrap=1000 to request that lavaan compute bootstrapped standard errors with 1000 bootstrapped samples. We actually don’t care much about the standard errors. What we really want are bootstrapped confidence intervals, which are generated in the parameterEstimates function with the boot.ci.type argument. The parameterEstimates function produces a simple list of the parameter estimates from the model. By including the boot.ci.type argument, we request that this output include 95% boostrapped confidence intervals.

Note that there exist multiple methods for calculating bootrapped CIs. The percentile method is probably easiest to understand – the 1000 boostrapped estimates are ordered by magnitude and the 25 th estimate (2.5 th percentile) and 975 th estimate (97.5 th percentile) are taken as the confidence limits, yielding a 95% confidence interval. This method, which is widely available in many software programs, is obtained via boot.ci.type = “perc”. That is the method we used in the lecture notes. A slightly preferable approach, however, is to use bias-corrected bootstrapped confidence intervals, and these are readily available in lavaan. To obtain the bias corrected confidence intervals, we simply use boot.ci.type = “bca.simple”. The biascorrected intervals are shown in the output below. In terms of null hypothesis testing, the same conclusions are generated with the bias-corrected CIs as with the percentile CIs presented in lecture, but there are some slight differences in the specific values of the confidence limits.

parameterEstimates(fit.5b, boot.ci.type = "perc")
parameterEstimates(fit.5b, boot.ci.type = "bca.simple")

The total effect of coa on peer is equal to .209 and represents a combination of the direct effect (.185) and the total indirect effect (.024). The 95% CI is equal to .094 and .306; because this does not contain zero, the total effect is deemed to be significant.

Examining the mediational pathways, we see that the specific indirect effect coa→stress→negaff→peer, labeled ind_s to indicate it is the indirect effect through stress, is equal to .015 (95% CI=.005, .036) and is significant (does not include zero). The biological pathway from coa→emotion→negaff→peer, labeled ind_e to indicate it is the indirect effect through emotion, is equal to .009 (95% CI=0, .022) and thus does not reach statistical significance (because the lower CI is equal to zero).

2. Factor Analysis

EFA

Latent variable also called: unmeasured variables, constructs, factors, true scores, unobserved variables, unobserved heterogeneity. Latent variable is used for: factors in factor analysis, latent variables in structural equation models, basis curves in latent curve analysis, latent classes (class/cluster/mixture models), latent traits, underlying propensity variables for censored/limited dependent variables, missing data, random effects in a multilevel or mixed model.

Goals of Factor Analysis: determine the underlying structure behind a set of observed measures.

Exploratory factor analysis is primarily data-driven: all observed variables regressed on all factors and the regression slopes. Confirmatory factory analysis is formally testing a theoretical factor structure, number and nature of latent variables specified by theory, relationships between indicators and latent variables specified by theory.

Outcome variable is regressed on the predictors. As the target predicted outcome y depends on the predictor x, you can say that “is regressed on” means “is dependent on”. The word “regressed” is used instead of “dependent” because we want to emphasise that we are using a regression technique to represent this dependency between x and y.

\(\Theta\) is residual covariance matrix

Communality. \(R^2\) for regression of the indicator on the set of common factors: items with high communalities are good items, as most of their variance reflects the influence of the common factors \[ h^2=1-\frac{VAR(\varepsilon)}{VAR(y)} \]

Conducting Process

  1. Determine number of latent factors
  2. Rotate factor pattern matrix at chosen number of factors
  3. Eliminate problematic items and refit model (items with large cross-loadings or with low communalities, redundant itmes otherwise may hijack the factor)
  4. Inspect final pattern matrix to determine meaning of latent factors

CFA

Setting the scale of latenet variables

  1. set means and variances of the latent variables to zero and one
    • puts latent variables on a standardized scale
    • allows for estimation of all factor loadings (and intercepts)
    • same loading scaling option that is used in EFA
  2. give each latent variable the same metric as one of the observed variables. The intercept and loading for the “scaling item” are set to zero and one

CFA Example dataset description— The data for this demonstration were provided by Holzinger & Swineford in their 1939 monograph A Study in Factor Analysis: The Stability of a Bi-Factor Solution. The sample includes 301 7th and 8th grade students, between 11-16 years of age, drawn from two schools. The data is in the text file hs.dat and the accompanying R-script file is ch04.R. The variables in the data set that we will use are

visperc visual perception test in which participants select the next image in a series

cubes visual perception test in which participants must mentally rotate a cube

lozenges visual perception test involving mental “flipping” of a parallelogram (“lozenge”)

parcomp paragraph comprehension test

sencomp sentence completion task in which participants select most appropriate word to put at the end of a sentence

wordmean verbal ability test in which participants must select a word most similar in meaning to a word used in a sentence.

addition participants have 2 minutes to complete as many 2-number addition problems as they can

countdot participants have 4 minutes to count the number of dots in each of a series of dot pictures

sccaps participants have 3 minutes to indicate whether capital letters are composed entirely of straight lines or include curved lines.

Other variables in the data not included in the models fit here are school, female, age, and month.

hs <- read.table("data/hs.dat", header=FALSE) 

names(hs) <- c("school", "female", "age", "month", "visperc", "cubes", "lozenges", "parcomp", "sencomp", "wordmean", "addition", "countdot", "sccaps")

rescaled the variables addition, countdot, and sccaps by dividing by four: This was done to facilitate model estimation, as numerical instability problems can arise when using variables on widely differing scales. Dividing these variables by four brings their standard deviations closer to the standard deviations of the other observed variables.

hs$addition <- hs$addition/4 
hs$countdot <- hs$countdot/4 
hs$sccaps <- hs$sccaps/4

Finally, we load the lavaan package that we will use to fit the CFA models:

cfa function in lavaan imposes a number of defaults consistent with how CFA models are typically specified and enables us to specify models with compact model syntax objects. The default scaling for the latent variables is a hybrid of the approaches we described in lecture. The default scaling for the latent variables is a hybrid of the approaches we described in lecture. By default, the latent variables will have means set to zero but freely estimated variance. Additionally, the factor loading of the first indicator for each latent variable will be set to one but the intercept for this indicator will be freely estimated. We will override these defaults to implement the scaling options described in lecture. in defining the model syntax object, we implement the =~ operator, which is used to define latent variables (left hand side) and to specify the variables that load on them (right hand side). Thus, visual =~ visperc + cubes + lozenges defines a new latent variable, visual, and indicates that visperc, cubes, and lozenges are indicator variables.

cfa.1a <-'#factor loadings
          visual =~ visperc + cubes + lozenges
          verbal =~ parcomp + sencomp + wordmean
          speed =~ addition + countdot + sccaps
         '

fit.1a <- cfa(cfa.1a, data=hs, meanstructure=TRUE, std.lv=TRUE)
summary(fit.1a, fit.measures=TRUE, standardized=TRUE, rsquare=TRUE)
lavaan 0.6-12 ended normally after 28 iterations

  Estimator                                         ML
  Optimization method                           NLMINB
  Number of model parameters                        30

  Number of observations                           301

Model Test User Model:
                                                      
  Test statistic                                85.306
  Degrees of freedom                                24
  P-value (Chi-square)                           0.000

Model Test Baseline Model:

  Test statistic                               918.852
  Degrees of freedom                                36
  P-value                                        0.000

User Model versus Baseline Model:

  Comparative Fit Index (CFI)                    0.931
  Tucker-Lewis Index (TLI)                       0.896

Loglikelihood and Information Criteria:

  Loglikelihood user model (H0)              -8326.241
  Loglikelihood unrestricted model (H1)      -8283.589
                                                      
  Akaike (AIC)                               16712.483
  Bayesian (BIC)                             16823.696
  Sample-size adjusted Bayesian (BIC)        16728.553

Root Mean Square Error of Approximation:

  RMSEA                                          0.092
  90 Percent confidence interval - lower         0.071
  90 Percent confidence interval - upper         0.114
  P-value RMSEA <= 0.05                          0.001

Standardized Root Mean Square Residual:

  SRMR                                           0.060

Parameter Estimates:

  Standard errors                             Standard
  Information                                 Expected
  Information saturated (h1) model          Structured

Latent Variables:
                   Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
  visual =~                                                             
    visperc           5.398    0.485   11.128    0.000    5.398    0.772
    cubes             1.992    0.310    6.429    0.000    1.992    0.424
    lozenges          5.249    0.595    8.817    0.000    5.249    0.581
  verbal =~                                                             
    parcomp           2.969    0.170   17.474    0.000    2.969    0.852
    sencomp           4.406    0.251   17.576    0.000    4.406    0.855
    wordmean          6.416    0.376   17.082    0.000    6.416    0.838
  speed =~                                                              
    addition          3.562    0.400    8.903    0.000    3.562    0.570
    countdot          3.655    0.330   11.090    0.000    3.655    0.723
    sccaps            6.030    0.585   10.305    0.000    6.030    0.665

Covariances:
                   Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
  visual ~~                                                             
    verbal            0.459    0.064    7.189    0.000    0.459    0.459
    speed             0.471    0.073    6.461    0.000    0.471    0.471
  verbal ~~                                                             
    speed             0.283    0.069    4.117    0.000    0.283    0.283

Intercepts:
                   Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
   .visperc          29.615    0.403   73.473    0.000   29.615    4.235
   .cubes            24.352    0.271   89.855    0.000   24.352    5.179
   .lozenges         18.003    0.521   34.579    0.000   18.003    1.993
   .parcomp           9.183    0.201   45.694    0.000    9.183    2.634
   .sencomp          17.362    0.297   58.452    0.000   17.362    3.369
   .wordmean         15.299    0.441   34.667    0.000   15.299    1.998
   .addition         24.069    0.360   66.766    0.000   24.069    3.848
   .countdot         27.635    0.291   94.854    0.000   27.635    5.467
   .sccaps           48.367    0.523   92.546    0.000   48.367    5.334
    visual            0.000                               0.000    0.000
    verbal            0.000                               0.000    0.000
    speed             0.000                               0.000    0.000

Variances:
                   Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
   .visperc          19.766    4.090    4.833    0.000   19.766    0.404
   .cubes            18.141    1.628   11.146    0.000   18.141    0.821
   .lozenges         54.037    5.800    9.317    0.000   54.037    0.662
   .parcomp           3.341    0.429    7.779    0.000    3.341    0.275
   .sencomp           7.140    0.934    7.642    0.000    7.140    0.269
   .wordmean         17.454    2.109    8.277    0.000   17.454    0.298
   .addition         26.430    2.691    9.823    0.000   26.430    0.676
   .countdot         12.192    1.855    6.573    0.000   12.192    0.477
   .sccaps           45.857    5.730    8.003    0.000   45.857    0.558
    visual            1.000                               1.000    1.000
    verbal            1.000                               1.000    1.000
    speed             1.000                               1.000    1.000

R-Square:
                   Estimate
    visperc           0.596
    cubes             0.179
    lozenges          0.338
    parcomp           0.725
    sencomp           0.731
    wordmean          0.702
    addition          0.324
    countdot          0.523
    sccaps            0.442

The modification indices for the model are obtained from the modindices function as follows:

modindices(fit.1a, sort.=TRUE, minimum.value=10)

Here we see the largest modification indices are associated with a cross-loading for sccaps on visual, and a correlated uniqueness for countdot with addition. It is important to keep in mind that both modification indices may be related to the same misspecification.

Initial Model with Scaling Items: model fit is the same

We shall choose the first indicator for each factor to be the scaling item. The intercept and factor loading for each scaling item is set to zero and one, respectively. This scaling option permits the means and variances of the latent factors to be estimated.

cfa.1b <-'#factor loadings
          visual =~ visperc + cubes + lozenges
          verbal =~ parcomp + sencomp + wordmean
          speed =~ addition + countdot + sccaps
     
          #means/intercepts
          visual ~ 1
          verbal ~ 1
          speed ~ 1
          visperc ~ 0*1
          parcomp ~ 0*1
          addition ~ 0*1
         '

fit.1b <- cfa(cfa.1b, data=hs, meanstructure=TRUE)
#summary(fit.1b, fit.measures=TRUE, standardized=TRUE, rsquare=TRUE)

cfa.2 <- '#factor loadings
          visual =~ visperc + cubes + lozenges + sccaps
          verbal =~ parcomp + sencomp + wordmean
          speed =~ addition + countdot + sccaps
         '
fit.2 <- cfa(cfa.2, data=hs, meanstructure=TRUE, std.lv=TRUE)
#summary(fit.2, fit.measures=TRUE, standardized=TRUE, rsquare=TRUE)

lavTestLRT(fit.2, fit.1a)
Chi-Squared Difference Test

       Df   AIC   BIC  Chisq Chisq diff Df diff Pr(>Chisq)    
fit.2  23 16682 16796 52.382                                  
fit.1a 24 16712 16824 85.305     32.923       1  9.586e-09 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
modindices(fit.2, sort.=TRUE, minimum.value=10)

Note that no further changes are suggested for the model.

cfa.3 <- '#factor loadings
          visual =~ visperc + cubes + lozenges 
          verbal =~ parcomp + sencomp + wordmean
          speed =~ addition + countdot + sccaps

          #covariances
          addition ~~ countdot
         '
fit.3 <- cfa(cfa.3, data=hs, meanstructure=TRUE, std.lv=TRUE)
#summary(fit.3, fit.measures=TRUE, standardized=TRUE, rsquare=TRUE)

lavTestLRT(fit.3, fit.1a)
Chi-Squared Difference Test

       Df   AIC   BIC  Chisq Chisq diff Df diff Pr(>Chisq)    
fit.3  23 16682 16797 53.272                                  
fit.1a 24 16712 16824 85.305     32.033       1  1.516e-08 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
modindices(fit.3, sort.=TRUE, minimum.value=10)

This model is not nested with the alternative modified model; however, the two models provide nearly equivalent fit (RMSEA=.065 versus .066, TLI=.948 versus .946, etc.). Thus, model selection should be based on which modification is most plausible, and upon the interpretability of parameter estimates.

3. LSEM

  1. the measurement model is identical to CFA \(y_i= v +\Lambda\eta_i + \varepsilon_i\)
  2. the structural model is similar to path analysis \(\eta_i=\alpha + B\eta_i + \Gamma x_i + \zeta_i\)

Measurement invariance (MI) refers to extent to which same measurements conducted under different conditions yield same measures of attributes under study. Longitudinal invariance is said to exist if the distribution of the observed variables depends only on the level of the latent variable and not also on the time point at which it was measured f(y|\(\eta\),t)= f(y|\(\eta\))

The latent growth curve is capturing the growth as a latent factor. The latent curve model (LCM) is fundamentally a highly restricted CFA model. The reduced-form equation is \(y_i= v +\Lambda(\alpha+\zeta_i) + \varepsilon_i\)

Time invariate predictor, predict both intercept and slope change structural model: add \(\Gamma x_i\) into it. \(y_i= v +\Lambda(\alpha+\Gamma x_i+\zeta_i) + \varepsilon_i\)

while time-invariant covariates add predictors into structual model, time-varying covariates add predictors into measurement model. add \(Kz_i\). \(y_i= v +\Lambda(\alpha+\zeta_i) +Kz_i+ \varepsilon_i\)

4. MLM

lme {nlme} function is flexible in autocorrelation structure

summary(lme(AIQ~1 + SZ +T1+T2+T3 + SZ:T1 + SZ:T2 + SZ:T3, random = ~T1+T2|ID, data = cog_pre_long, na.action = na.omit,
     correlation = corCompSymm(form =  ~ 1 | ID),method = "ML", 
     control =list(msMaxIter = 1000, msMaxEval = 1000)))

lmer {lme4}

summary(lmer(AIQ ~ 1 + SZ +T1+T2+T3 + SZ:T1 + SZ:T2 + SZ:T3 + (1+T1+T2|ID), data=cog_dat_long))
LS0tCnRpdGxlOiAiU0VNIgpvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6IAogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogNgotLS0KCmBgYHtyIG1hbmFnZSBwYWNrZWdlc30KcGFjbWFuOjpwX2xvYWQocmVhZHhsLHJlc2hhcGUsc3Vydml2YWwsc3Vydm1pbmVyLGdncGxvdDIsY293cGxvdCxkcGx5cixNeS5zdGVwd2lzZSxoYXZlbix0aWR5cixrbml0cixsdWJyaWRhdGUsbmFuaWFyLHRhYmxlMSwgSG1pc2Msc2tpbXIscHN5Y2gsbGF2YWFuKQpgYGAKCiMjIyAxLiBQYXRoIEFuYWx5c2lzClN0cnVjdHVyYWwgRXF1YXRpb24gTW9kZWwgKFNFTSkgc2kgYSBnZW5lcmFsIGFuYWx5dGljIGZyYW1ld29yayB0aGF0IGluY2x1ZGUgdC10ZXN0LCBBTk9WQSwgTUFOT1ZBLCBtdWx0aXBsZSByZWdyZXNzaW9uLCBwYXRoIGFuYWx5c2lzLGZhY3RvciBhbmFseXNpcywgZ3Jvd3RoIHRyYWplY3Rvcmllcy4KCiMjIyMgMS4wIE92ZXJhbGwgQ29uY2VwdHMKCjEuICoqU3BlY2lmaWNhdGlvbioqCgpQcmVkaWN0b3IsIE91dGNvbWVzLCBNZWRpYXRvcnMsIEZhY3RvcnMuIFVzZSAqKlBhdGggRGlhZ3JhbXMqKiBmb3Igc3BlY2lmaWNhdGlvbgoKMi4gKipJZGVudGlmaWNhdGlvbioqCiAgICArIHRoZSAqKnQtcnVsZSoqOiAkayA9IFxmcmFjeyhwK3EpKHArcSsxKX17Mn0rKHArcSkkLCBudW1iZXIgb2YgcGFyYW1ldGVycyBtdXN0ICRcbGUkay4gTmVjZXNzYXkgYnV0IG5vdCBzdWZmaWNpZW50CiAgICArIHRoZSAqKk51bGwgQiBydWxlKio6ICRcbWF0aGJme3lfaT0gXGFscGhhKyBCeV9pKyBcR2FtbWEgeF9pKyBcemV0YV9pfSQsIHdoZW4gKipCKio9MCwgdGhlcmUgaXMgbm8gcmVsYXRpb25zIGFtb25nIHRoZSBEVnMuIFN1ZmZpY2llbnQKICAgICsgdGhlICoqcmVjdXJzaXZlIHJ1bGUqKjogbm8gZmVlZGJhY2sgb3IgYmktZGlyZWN0aW9uYWwgZWZmZWN0cywgbm8gY29ycmVsYXRlZCByZXNpZHVhbHMuIFN1ZmZpY2llbnQgYnV0IG5vdCBuZWNlc3NhcnkuCiAgICArIHRoZSAqKmNvbW1vbiBzZW5zZSBydWxlKioKCnBvc3NpYmxlIHRvIG9idGFpbiBhbGwgbW9kZWwgcGFyYW1ldGVyIGVzdGltYXRlcz8KCk1vZGVsLUltcGxpZWQgTW9tZW50czogTW9kZWwgaXMgYSAqKnNldCBvZiBwYXJhbWV0ZXJzKiouIFBvcHVsYXRpb24gTW9tZW50cyBpbmNsdWRlICoqbWVhbnMgYW5kIGNvdmFyaWFuY2UqKi4gTW9kZWwtSW1wbGllZCBNb21lbnRzIGlzIG1vbWVudCBtYXRyaXggaW1wbGllZCBieSB0aGUgbW9kZWwsIHdoaWNoIGlzICoqc2ltaWxhciB0byB5IGFuZCAkXGhhdHt5fSQqKi4gY2FuIGVhY2ggcGFyYW1ldGVyIGJlIHVuaXF1ZWx5IGV4cHJlc3NlZCB1c2luZyBvYnNlcnZlZCBpbmZvcm1hdGlvbj8gRXh0ZW50IHRvIHdoaWNoIHRoZXJlIGlzIHN1ZmZpY2llbnQga25vd24gaW5mb3JtYXRpb24gdG8gaW5mZXIgdW5rbm93biB2YWx1ZXMuICoqT3Zlci1pZGVudGlmaWVkKiogaXMgb2JzZXJ2ZWQgPiBlc3RpbWF0ZWQuIHBvcHVsYXRpb24gbW9tZW50cyBhcmUgJFxTaWdtYSQgYW5kICRcbXUkLiBTYW1wbGUgbW9tZW50cyBhcmUgUyBhbmQgbS4gcG9wdWxhdGlvbiBtb2RlbC1pbXBsaWVkIG1vbWVudHMgYXJlICAkXFNpZ21hKFx0aGV0YSkkIGFuZCAkXG11KFx0aGV0YSkkCgozLiAqKkVzdGltYXRpb24qKgoKSG93IHRvIG9idGFpbiBiZXN0IGVzdGltYXRlcy4gTUwgaXMgYXN5bXB0b3RpY2FsbHkgdW5iaWFzZWQsY29uc2lzdGVudCwgYW5kIG1heGltYWxseSBlZmZpY2llbnQuIAoKNC4gKipFdmFsdWF0aW9uKioKICAgICsgKipSIHNxdWFyZSoqOiB2YXJpYW5jZSBleHBsYWluZWQgYnkgdGhlIG1vZGVsCiAgICArICoqQ2hpLVNxdWFyZSBUZXN0IFN0YXRpc3RpY3MqKjogY29tcGFyZSB3aXRoIHRoZSBzYXR1cmF0ZWQgbW9kZWwgd2hpY2ggaW1wb3NlIG5vIHJlc3RyaWN0aW9ucyBvbiBtZWFucyBvciBjb3ZhcmlhbmNlcy4gbm9uLXNpZ25pZmljYW50IG1lYW5zIHRoZSB0ZXN0ZWQgbW9kZWwgaXMgZ29vZC4gUG9vcmx5IGZpdHRpbmcgbW9kZWwgY2FuIGJlIGFjY2VwdGVkIGJlY2F1c2UgdGhlcmUgaXMgaW5zdWZmaWNpZW50IHBvd2VyIHRvIGRldGVjdCB0aGUgbWlzc3BlY2lmaWNhdGlvbi4gKipVc2VkIGZvciBuZXN0ZWQgbW9kZWwgY29tcGFyaXNvbioqLiAKICAgICsgUmVsYXRpdmUgR29vZG5lc3Mgb2YgRml0IEluZGljZXM6KipUTEksQ0ZJLCBJRkkqKiAqKj4wLjk1IGlzIGdvb2QqKi4gYmFzZWxpbmUgbW9kZWwsIGFsbCBtZWFuIGFuZCB2YXJpYW5jZSBhbmQgbm8gY292YXJpYW5jZS4gaHlwb3RoZXNpemVkIG1vZGVsIGlzIHRoZSB0ZXN0ZWQgbW9kZWwuCiAgICArIEFic29sdXRlIEdvb2RuZXNzIG9mIEZpdCBJbmRpY2VzOiAqKlJNU0VBKiogKCRcbGUkICoqMC4wNSBpcyBleGNlbGxlbnQqKjsgJFxsZSQgMC4wOCBtb2RlcmF0ZSBmaXQ7ID4xLjAgaXMgcG9vcikuIFN0YW5kYXJkaXplZCBSb290IE1lYW4gU3F1YXJlIFJlc2lkdWFsICoqU1JNUioqICgkXGxlJCAqKi4wOCBpcyBnb29kKiosIG5vdCBwZW5hbGl6ZWQgZm9yIHRoZSBudW1iZXIgb2YgbW9kZWwgcGFyYW1ldGVycywgc28gdGVuZHMgdG8gYmUgYmV0dGVyIGZvciBsZXNzIHJlc3RyaWN0ZWQgbW9kZWxzKS4KCkhvdyB3ZWxsIGRvZXMgdGhlIG1vZGVsIGZpdCB0aGUgZGF0YS4gUmVsYXRpdmUgZml0IG9mIGNvbXBldGluZyBtb2RlbHMgY2FuIGJlIGNvbXBhcmVkIHVzaW5nIGxpa2VsaWhvb2QgcmF0aW8gdGVzdHMgKGNoaS1zcXVhcmUgZGlmZmVyZW5jZSB0ZXN0cykuICoqUmVncmVzc2lvbnMgYXJlIGp1c3QtaWRlbnRpZmllZCoqLCB1c2VzIHRoZSBzYW1lIG51bWJlciBvZiBwYXJhbWV0ZXJzIHRvIGV4YWN0bHkgcmVwcm9kdWNlIHRoZSBvYnNlcnZlZCBtb21lbnRzLiBTbyB0aGUgbW9kZWwgbmVjZXNzYXJpbHkgZml0cyBwZXJmZWN0bHkgYW5kIGlzIHNhaWQgdG8gYmUgKipzYXR1cmF0ZWQqKi4gTW9zdCBTRU1zLCBhcmUgb3Zlci1pZGVudGlmaWVkLCByZXN1bHRpbmcgdGVzdGFibGUgcmVzdHJpY3Rpb25zIG9uIG1vZGVsLWltcGxpZWQgbW9tZW50cy4KICAgICAKNS4gUG90ZW50aWFsICoqcmUtc3BlY2lmaWNhdGlvbioqCiAgICArICoqTW9kaWZpY2F0aW9uIEluZGljZXMgKE1JcykqKjogZXhwZWN0ZWQgY2hhbmdlIChiYXNlZCBvbiBtb2RlbCBkZXJpdmF0aXZlcyBub3QgYWN0dWFsIGxpa2VsaWhvb2QgcmF0aW8gdGVzdHMuIGJ1dCB2ZXJ5IGNsb3NlIGVzdGltYXRlcykuIENhbGN1bGF0ZWQgZm9yIGV2ZXJ5IHBhcmFtZXRlciB0aGF0IGlzIHJlc3RyaWN0ZWQuIFRha2Ugb25lIGF0IGEgdGltZSwgZW50aXJlZGx5IGRhdGEgZHJpdmVuCgpDYW4gdGhlIG1vZGVsIGJlIGltcHJvdmVkPyBIb3cgYXJlIG1vZGlmaWNhdGlvbnMgaWRlbnRpZmllZAoKNi4gKipJbnRlcnByZXRhdGlvbioqCgpXaGljaCBlZmZlY3RzIGFyZSBzaWduaWZpY2FudD8gV2hpY2ggYXJlIHN1YnN0YW4KCiogRGlzdHVyYmFuY2U6IHVuZXhwbGFpbmVkIHZhcmlhbmNlIG9mIGFuIGVuZG9nZW5vdXMgdmFyaWFibGUuIHRoZSBwYXJ0IHRoYXQgaXMgdW5yZWxhdGVkIHRvIHRoZSBwcmVkaWN0b3JzCgojIyMjIDEuMSBEYXRhc2V0IERlc2NyaXB0aW9uOiBEZXZpYW50IFBlZXIgQWRkaWxpYXRpb25zIApyZWFkICBEZXZpYW50IFBlZXIgQWRkaWxpYXRpb25zIGRhdGFzZXQKVGhlIGhlYWRlciBhcmd1bWVudCBvZiB0aGUgcmVhZC50YWJsZSBmdW5jdGlvbiBpcyBzZXQgdG8gRkFMU0UgaGVyZSB0byBpbmRpY2F0ZSB0aGF0IHRoZXJlIGFyZSBubyB2YXJpYWJsZSBuYW1lcyBhdCB0aGUgdG9wIG9mIHRoZSBkYXRhIGZpbGUuCmBgYHtyIH0KYWZkcCA8LSByZWFkLnRhYmxlKCJkYXRhL2FmZHAuZGF0IiwgaGVhZGVyID0gRkFMU0UgLGNvbC5uYW1lcyA9YygiaWQiLCJjb2EiLCJhZ2UiLCJnZW4iLCJzdHJlc3MiLCJlbW90aW9uIiwibmVnYWZmIiwicGVlciIpKQpwc3ljaDo6ZGVzY3JpYmUoYWZkcCkKYGBgCioqcGVlcioqIGFkb2xlc2NlbnQgcmVwb3J0IG9uIHBlZXIgc3Vic3RhbmNlIHVzZSBhbmQgcGVlciB0b2xlcmFuY2Ugb2YgdXNlCgoqKmNvYSoqIHBhcmVudCByZXBvcnQgb2YgYWxjb2hvbGlzbSBkaWFnbm9zaXMgd2hlcmUgMD1ub24tYWxjb2hvbGljIGFuZCAxPWFsY29ob2xpYwoKKipnZW4qKiBnZW5kZXIgMD1naXJsIDE9Ym95CgoqKmFnZSoqIGFnZSBtZWFzdXJlZCBpbiB5ZWFycyBhdCBhc3Nlc3NtZW50CgoqKnN0cmVzcyoqIHNlbGYgcmVwb3J0IG1lYXN1cmUgb2YgdW5jb250cm9sbGFibGUgbmVnYXRpdmUgbGlmZSBzdHJlc3NmdWwgZXZlbnRzCgoqKmVtb3Rpb24qKiBzZWxmIHJlcG9ydCBtZWFzdXJlIG9mIHRlbXBlcmFtZW50YWwgZW1vdGlvbmFsIGV4cHJlc3NpdmVuZXNzCgoqKm5lZ2FmZioqIHNlbGYgcmVwb3J0IG1lYXN1cmUgb2YgZGVwcmVzc2lvbiBhbmQgYW54aWV0eQoKCiMjIyMgMS4yIFNpbXBsZSBSZWdyZXNzaW9uCgohW10oZmlndXJlL1NpbXBsZVJncmVzc2lvbi5qcGcpe3dpZHRoPTUwJX0KcGVlciA9IM6xICsgzrMgY29hICsgzrYKCkZpcnN0LCB3ZSBuZWVkIHRvIGNyZWF0ZSB3aGF04oCZcyBjYWxsZWQgYSAqKm1vZGVsIHN5bnRheCBvYmplY3QqKi5UaGVuIGZpdCB0aGUgbW9kZWwgdXNpbmcgdGhlICoqc2VtIGZ1bmN0aW9uKiosIHBsYWNpbmcgdGhlIHJlc3VsdHMgaW50byB0aGUgZGF0YSBvYmplY3QgZml0LiBOb3RlIHRoYXQgd2UgaW5jbHVkZSB0aGUgKiptZWFuc3RydWN0dXJlKiogYXJndW1lbnQgd2l0aCB0aGUgc2VtIGZ1bmN0aW9uIHNvIHRoYXQgd2Ugd2lsbCBvYnRhaW4gYW4gZXN0aW1hdGUgb2YgdGhlIHJlZ3Jlc3Npb24gaW50ZXJjZXB0LgpgYGB7cn0KbW9kZWwuMSA8LSAncGVlciB+IGNvYScKc3VtbWFyeShzZW0obW9kZWwuMSwgZGF0YT1hZmRwLCBtZWFuc3RydWN0dXJlPVRSVUUpLHN0YW5kYXJkaXplZD1UUlVFLHJzcXVhcmU9VFJVRSkKYGBgCndlIGFyZSB1c2luZyBNTCAobWF4aW11bSBsaWtlbGlob29kKSBlc3RpbWF0aW9uIHdpdGggdGhlICoqbmxtaW5iIG9wdGltaXplcioqICh0aGlzIGlzIGEgYnVpbHQtaW4gb3B0aW1pemVyIGluIFIgZm9yIGZpbmRpbmcgdGhlIG1pbmltdW0gb2YgYSBmdW5jdGlvbikuCgpJdCBpcyB3b3J0aCBwYXVzaW5nIGhlcmUgdG8gbm90ZSB0aGF0ICoqbGF2YWFuIGNvdW50cyBwYXJhbWV0ZXJzIGRpZmZlcmVudGx5KiogdGhhbiB3ZSBkZXNjcmliZWQgaW4gbGVjdHVyZS4gRm9yIHRoaXMgbW9kZWwsIHdlIHdvdWxkIG5vcm1hbGx5IGNvdW50IGZpdmUgcGFyYW1ldGVycywgdGhlIG1lYW4gYW5kIHZhcmlhbmNlIG9mIENPQSwgdGhlIGludGVyY2VwdCBhbmQgc2xvcGUgb2YgdGhlIHJlZ3Jlc3Npb24gb2YgUGVlciBvbiBDT0EsIGFuZCB0aGUgcmVzaWR1YWwgdmFyaWFuY2Ugb2YgUGVlci4gQnV0IGxhdmFhbiAqKmRvZXMgbm90IGNvdW50IHRoZSBtZWFuIG9yIHZhcmlhbmNlIG9mIHRoZSBwcmVkaWN0b3IqKiwgQ09BLCBhcyBwYXJhbWV0ZXJzIG9mIHRoZSBtb2RlbC4gTm9yIGRvZXMgaXQgY291bnQgKipjb3ZhcmlhbmNlcyBhbW9uZyBwcmVkaWN0b3JzKiogKHRob3VnaCB0aGVyZSBhcmUgbm8gc3VjaCBjb3ZhcmlhbmNlcyBpbiB0aGUgY3VycmVudCBtb2RlbCkgYXMgZnJlZSBwYXJhbWV0ZXJzLiBGb3J0dW5hdGVseSwgbGF2YWFuIGFsc28gZG9lcyBub3QgY291bnQgdGhlc2UgcGFyYW1ldGVycyB3aGVuIGRldGVybWluaW5nIHRoZSBudW1iZXIgb2Ygb2JzZXJ2ZWQgbW9tZW50cywgc28gdGhlIGRlZ3JlZXMgb2YgZnJlZWRvbSBmb3IgdGhlIHRlc3Qgc3RhdGlzdGljIHdvcmsgb3V0IHJlZ2FyZGxlc3MgKGUuZy4sIGhlcmUgaXQgbmVpdGhlciBjb3VudHMgdGhlIG1lYW4gYW5kIHZhcmlhbmNlIG9mIENPQSBhcyBvYnNlcnZlZCBtb21lbnRzIG5vciBkb2VzIGl0IGNvdW50IHRoZW0gYXMgZXN0aW1hdGVkIG1vbWVudHMsIGxlYXZpbmcgYSBuZXQgZGlmZmVyZW5jZSBvZiB6ZXJvIHdoZW4gY2FsY3VsYXRpbmcgdGhlIGRlZ3JlZXMgb2YgZnJlZWRvbSkuCgpUaGlzIG91dHB1dCBhbHNvIHByb3ZpZGVzIHNvbWUgaW5mb3JtYXRpb24gYWJvdXQgbW9kZWwgZml0LiAqKk11bHRpcGxlIHJlZ3Jlc3Npb24gbW9kZWxzIGFyZSBqdXN0IGlkZW50aWZpZWQqKiAoaS5lLiwgZXZlcnkgcGllY2Ugb2YgaW5mb3JtYXRpb24gcHJvdmlkZWQgYnkgdGhlIHNhbXBsZSBpcyDigJh1c2VkIHVw4oCZIHRvIGVzdGltYXRlIG1vZGVsIHBhcmFtZXRlcnMgc28gdGhhdCBubyBkZWdyZWVzIG9mIGZyZWVkb20gcmVtYWluKS4gVGhlcmVmb3JlLCB0aGUgbW9kZWwgZml0cyB0aGUgZGF0YSBwZXJmZWN0bHkgYW5kIGl0IGlzIG5vdCB3b3J0aHdoaWxlIHRvIGludGVycHJldCB0aGUgdGVzdCBzdGF0aXN0aWMgKHRoaXMgYW5kIG90aGVyIGZpdCBpbmRpY2VzIHdpbGwgYmUgZGlzY3Vzc2VkIGluIGxhdGVyIHNlY3Rpb25zKS4KClRoZSBvdXRwdXQgaXMgc3ViZGl2aWRlZCBpbnRvICoqdGhyZWUgcGFydHMsIHJlZ3Jlc3Npb25zLCBpbnRlcmNlcHRzLCBhbmQgdmFyaWFuY2VzKiouIEluIHRoZSBSZWdyZXNzaW9ucyBzZWN0aW9uLCB0aGUgcGVlciB+IGNvYSBjb2VmZmljaWVudCBpcyB0aGUgc2xvcGUgcGFyYW1ldGVyIGVzdGltYXRlIM6zIC4gSW4gdGhlIMuGIEludGVyY2VwdHMgc2VjdGlvbiwgdGhlIGNvZWZmaWNpZW50IGxpc3RlZCBmb3IgLnBlZXIgaXMgdGhlIGludGVyY2VwdCDOsSAuIEZpbmFsbHksIGluIHRoZSBWYXJpYW5jZXMgc2VjdGlvbiwgdGhlIGNvZWZmaWNpZW50IGxpc3RlZCBmb3IgLnBlZXIgaXMgdGhlIHJlcHJlc2VudHMgcmVwcmVzZW50cyDPiCAsIHRoZSBlc3RpbWF0ZWQgdmFyaWFuY2Ugb2YgzrYgaSAoaS5lLiwgcmVzaWR1YWwgdmFyaWFuY2UpLiBUaGUgRXN0aW1hdGUgY29sdW1uIGxpc3RzIGlzIHRoZSBNTCBwb2ludCBlc3RpbWF0ZSBvZiBlYWNoIHBhcmFtZXRlci4gVGhlIFN0ZC5FcnIgY29sdW1uIGdpdmVzIHRoZSBzdGFuZGFyZCBlcnJvciBmb3IgZWFjaCBlc3RpbWF0ZSAod2hlcmUgdGhlc2UgYXJlIGNvbXB1dGVkIHVzaW5nIHRoZSBleHBlY3RlZCBpbmZvcm1hdGlvbiBtYXRyaXgsIGFzIG5vdGVkIGFib3ZlKS4gTmV4dCwgdGhlIHotdmFsdWUgY29sdW1uIHJlcG9ydHMgdGhlIFdhbGQgei1zdGF0aXN0aWMgZm9yIHRoZSBudWxsIGh5cG90aGVzaXMgdGVzdCB0aGF0IHRoZSBwYXJhbWV0ZXIgaXMgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgZnJvbSB6ZXJvIGluIHRoZSBwb3B1bGF0aW9uLCBhbmQgdGhlIFAoPnx6fCkgY29sdW1uIHJlcG9ydHMgdGhlIHAtdmFsdWUgYXNzb2NpYXRlZCB3aXRoIHRoaXMgei1zdGF0aXN0aWMuCgpIZXJlLCB3ZSBzZWUgdGhhdCB0aGUgYXZlcmFnZSAqKm5vbi1DT0EgaGFzIGEgc2NvcmUgb2YgLjI5OCoqIG9uIHBlZXIgYW5kIHRoZSBhdmVyYWdlICoqQ09BKiogaGFzIGEgc2NvcmUgdGhhdCBpcyAuMTc2IHVuaXRzIGhpZ2hlciB0aGFuIG5vbi1DT0FzIG9uIHBlZXIgKCoqLjI5OCArIC4xNzYgPSAuNDc0KiopLiBCb3RoIHRoZSBpbnRlcmNlcHQgYW5kIHNsb3BlIGFyZSBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBmcm9tIHplcm8uIEZpbmFsbHksIHRoZSAqKnZhcmlhbmNlKiogaW4gZGV2aWFudCBwZWVyIGFzc29jaWF0aW9uIHRoYXQgaXMgKipub3QgZXhwbGFpbmVkIGJ5IENPQSBzdGF0dXMgaXMgLjI4MCoqLiBUaGlzIGluZGljYXRlcyB0aGF0LCBhbHRob3VnaCBDT0Egc3RhdHVzIGlzIGEgc2lnbmlmaWNhbnQgcHJlZGljdG9yIG9mIHBlZXIsIENPQSBzdGF0dXMgZG9lcyBub3QgZnVsbHkgYWNjb3VudCBmb3IgYWZmaWxpYXRpb24gd2l0aCBwZWVycy4KCkJlY2F1c2UgcGVlciBpcyBub3Qgb24gYW4gaW50cmluc2ljYWxseSBtZWFuaW5nZnVsIHNjYWxlLCB3ZSBjYW5ub3QgZWFzaWx5IGludGVycHJldCB0aGUgZGlmZmVyZW5jZXMgYW1vbmcgdGhlIHJlZ3Jlc3Npb24gcGFyYW1ldGVycyBvciByZXNpZHVhbCB2YXJpYW5jZXMuIFRvIGJldHRlciBpbnRlcnByZXQgdGhlc2UgcmVzdWx0cywgd2UgY2FuIHJlcXVlc3QgKipzdGFuZGFyZGl6ZWQgZXN0aW1hdGVzKiouIFdpdGhpbiBsYXZhYW4sIHNldmVyYWwgbWV0aG9kcyBvZiBzdGFuZGFyZGl6YXRpb24gYXJlIGF2YWlsYWJsZSB3aXRoaW4gdGhlIHN1bW1hcnkgZnVuY3Rpb24uIFRoZSBmaXJzdCB0eXBlLCBvYnRhaW5lZCBieSBpbmNsdWRpbmcgKipzdGFuZGFyZGl6ZWQ9VFJVRSoqLCBpcyB0aGUgdHlwaWNhbCBmdWxseSBzdGFuZGFyZGl6ZWQgc29sdXRpb24uIEluIHRoaXMgY2FzZSwgKipib3RoIHRoZSBpbmRlcGVuZGVudCBhbmQgZGVwZW5kZW50IHZhcmlhYmxlcyBhcmUgc3RhbmRhcmRpemVkIHRvIGhhdmUgYSB2YXJpYW5jZSBvZiAxKiogKG5vdGUgdGhhdCBsYXZhYW4gZG9lcyAqKm5vdCoqLCBob3dldmVyLCBhbHNvICoqbWFrZSB0aGUgbWVhbnMgMCoqLCBhcyBvbmUgbWlnaHQgZXhwZWN0KS4gCgpUaGUgKipTdGQubHYqKiBjb2x1bW4gcmVmZXJzIHRvIGEgc29sdXRpb24gaW4gd2hpY2ggKipvbmx5IHRoZSBsYXRlbnQgdmFyaWFibGVzIGFyZSBzdGFuZGFyZGl6ZWQgYW5kIG5vdCB0aGUgb2JzZXJ2ZWQgdmFyaWFibGVzKiouIFNpbmNlIHRoZSBjdXJyZW50IG1vZGVsIGNvbnRhaW5zIG5vIGxhdGVudCB2YXJpYWJsZXMsIHRoaXMgaXMgb2YgbGl0dGxlIHVzZSBoZXJlLiBUaGUgKipTdGQuYWxsKiogY29sdW1uIGNvbnRhaW5zIHRoZSBmdWxseSBzdGFuZGFyZGl6ZWQgZXN0aW1hdGVzIG9mIGludGVyZXN0LCBpbiB3aGljaCBhbGwgdmFyaWFibGVzIChvYnNlcnZlZCBhbmQgbGF0ZW50KSBhcmUgc3RhbmRhcmRpemVkIHRvIGhhdmUgYSB2YXJpYW5jZSBvZiBvbmUuIFRodXMsIHdlIHNheSB0aGF0IGEgb25lIHN0YW5kYXJkIGRldmlhdGlvbiBpbmNyZWFzZSBpbiBDT0Egc3RhdHVzIGlzIGFzc29jaWF0ZWQgd2l0aCBhIC4xNjQgc3RhbmRhcmQgZGV2aWF0aW9uIGluY3JlYXNlIGluIGRldmlhbnQgcGVlciBhc3NvY2lhdGlvbnMuCgpJdCBtYXkgYmUgbW9yZSB1c2VmdWwgdG8gcmV0YWluIHRoZSBvcmlnaW5hbCBzY2FsaW5nIG9mIENPQSB3aGlsZSBzdGFuZGFyZGl6aW5nIHBlZXIuIElmIHdlIGluY2x1ZGUgKipzdGQubm94PVRSVUUqKiBpbiB0aGUgc3VtbWFyeSBmdW5jdGlvbiwgYXMgc2hvd24gYmVsb3csIHdlIHdpbGwgb2J0YWluIGVzdGltYXRlcyBpbiB3aGljaCB0aGUgbGF0ZW50IHZhcmlhYmxlcyBhbmQgZW5kb2dlbm91cyBvYnNlcnZlZCB2YXJpYWJsZXMgYXJlIHN0YW5kYXJkaXplZCBidXQgdGhlIGV4b2dlbm91cyBvYnNlcnZlZCB2YXJpYWJsZXMgYXJlIGxlZnQgaW4gdGhlaXIgcmF3IHNjYWxlLiBUaGVzZSBhcmUgY29tbW9ubHkga25vd24gYXMgcGFydGlhbGx5IHN0YW5kYXJkaXplZCBlc3RpbWF0ZXMuCgpGaW5hbGx5LCB3ZSBjYW4gYWxzbyBjYWxjdWxhdGUgaG93IG11Y2ggdmFyaWFuY2UgaXMgZXhwbGFpbmVkIGluIHBlZXIgYnkgY29hIGJ5IHJlcXVlc3RpbmcgdGhhdCBsYXZhYW4gb3V0cHV0IHRoZSByLXNxdWFyZWQgc3RhdGlzdGljLiAqKlItU3F1YXJlKiogaXMgdGhlIGVzdGltYXRlZCAqKnByb3BvcnRpb24gb2YgdmFyaWFuY2UqKiBpbiBwZWVyIHRoYXQgKippcyBhY2NvdW50ZWQgZm9yIGJ5IHRoZSBtb2RlbHMqKiAoaS5lLiwgQ09BLCB0aGUgb25seSBwcmVkaWN0b3IgaW5jbHVkZWQgaW4gdGhpcyBtb2RlbCkuIFdlIGhhdmUgZXhwbGFpbmVkIGxlc3MgdGhhbiAzJSBvZiB0aGUgdG90YWwgdmFyaWFuY2UgaW4gcGVlciB3aXRoIHRoZSBDT0EgcHJlZGljdG9yLiBOb3RlLCBob3dldmVyLCB0aGF0IG1lYXN1cmVkIHZhcmlhYmxlIHJlZ3Jlc3Npb24gbW9kZWxzIGFzc3VtZSB0aGF0IG5vIG1lYXN1cmVtZW50IGVycm9yIGlzIHByZXNlbnQuIElmIG1lYXN1cmVtZW50IGVycm9yIGlzIHByZXNlbnQsIHRoZSBlc3RpbWF0ZWQgcmVsYXRpb25zaGlwIGFtb25nIHRoZSB2YXJpYWJsZXMgaW4gdGhlIG1vZGVsIG1heSBiZSBhdHRlbnVhdGVkIGFuZCB0aGUgUiAyIHZhbHVlIHdpbGwgYWxzbyBiZSB1bmRlcmVzdGltYXRlZC4KCgoKCgojIyMjIDEuMyBNdWx0aXBsZSBSZWdyZXNzaW9uCiFbXShmaWd1cmUvTXVsdGlwbGVSZWdyZXNzaW9uLmpwZyl7d2lkdGg9NTAlfQpwZWVyID0gzrEgKyDOszFjb2EgKyDOsyAyZ2VuICsgzrMgM2FnZSArIM62IAoKd2UgaGF2ZSBzcGVjaWZpZWQgdGhhdCBwZWVyIGlzIHJlZ3Jlc3Npb24gb24gY29hLCBnZW4sIGFuZCBhZ2UuIE5vdGUgdGhhdCwgYWdhaW4sIHdlIHVzZSB0aGUgKipyZWdyZXNzaW9uIG9wZXJhdG9yIH4gKiogdG8gaW5kaWNhdGUgdGhlIHJlZ3Jlc3Npb24uIE5vdyB0aGF0IG91ciBtb2RlbCBpbmNsdWRlcyBtdWx0aXBsZSBwcmVkaWN0b3JzLCB3ZSB1c2UgdGhlICsgb3BlcmF0b3IgaW4gYmV0d2VlbiBlYWNoIHByZWRpY3Rvci4KYGBge3J9CnN1bW1hcnkoIHNlbSgncGVlciB+IGNvYSArIGdlbiArIGFnZScsIGRhdGE9YWZkcCwgbWVhbnN0cnVjdHVyZT1UUlVFKSwgc3RkLm5veD1UUlVFLCByc3F1YXJlPVRSVUUpCmBgYApXZSBzZWUgdGhhdCBnZW4gaXMgbm90IGEgc2lnbmlmaWNhbnQgcHJlZGljdG9yIG9mIHBlZXIgd2hlbiBDT0EgYW5kIGFnZSBhcmUgYWxzbyBpbmNsdWRlZCBpbiB0aGUgbW9kZWwgKHAgPSAuMzgxKS4gSG93ZXZlciwgYWdlIGlzIHNpZ25pZmljYW50bHkgcmVsYXRlZCB3aXRoIHBlZXIgc3VjaCB0aGF0IG9sZGVyIGFkb2xlc2NlbnRzIGFyZSBtb3JlIGxpa2VseSB0byBhc3NvY2lhdGUgd2l0aCBkZXZpYW50IHBlZXJzLiBXZSBlc3RpbWF0ZSB0aGF0IGEgb25lLXllYXIgaW5jcmVhc2UgaW4gYWdlIGlzIGFzc29jaWF0ZWQgd2l0aCBhIC4xNTEtaW5jcmVhc2UgaW4gZGV2aWFudCBwZWVyIGFzc29jaWF0aW9uIHJhdGluZ3MuIENPQSByZW1haW5zIGEgc2lnbmlmaWNhbnQgcHJlZGljdG9yIG9mIHBlZXIsIGFuZCB0aGUgcmVncmVzc2lvbiBwYXJhbWV0ZXIgKiplc3RpbWF0ZSAoaS5lLiwgaXQgaGFzIGluY3JlYXNlZCBmcm9tIC4xOCB0byAuMjEpIGhhcyBub3QgY2hhbmdlZCBtdWNoKiogZnJvbSB0aGUgc2luZ2xlLXByZWRpY3RvciBtb2RlbCB0byB0aGUgbXVsdGlwbGUtcHJlZGljdG9yIG1vZGVsICoqcmVsYXRpdmUgdG8gaXRzIHN0YW5kYXJkIGVycm9yICgwLjA2KSoqLiBUaGUgKipzdGFiaWxpdHkqKiBvZiB0aGlzIGNvZWZmaWNpZW50ICoqcmVmbGVjdHMqKiB0aGUgZmFjdCB0aGF0ICoqQ09BIGlzIG5vdCBoaWdobHkgY29ycmVsYXRlZCB3aXRoIGdlbiBvciBhZ2UqKi4KClRvIGJldHRlciBpbnRlcnByZXQgdGhlc2UgcmVzdWx0cywgYW5kIHRvIGdldCBhIHNlbnNlIGZvciB0aGUgcmVsYXRpdmUgY29udHJpYnV0aW9uIG9mIGVhY2ggcHJlZGljdG9yLCB3ZSByZXF1ZXN0ZWQgdGhlICoqcGFydGlhbGx5IHN0YW5kYXJkaXplZCBzb2x1dGlvbioqLiBXZSBwcmVmZXIgdGhpcyBtZXRob2Qgb2Ygc3RhbmRhcmRpemF0aW9uIGZvciB0aGlzIGV4YW1wbGUgYmVjYXVzZSAqKmFsbCB0aHJlZSBwcmVkaWN0b3JzIGhhdmUgbmF0dXJhbCBzY2FsZXMqKi4gQXMgY2FuIGJlIHNlZW4gaW4gdGhlIFN0ZC5ub3ggY29sdW1uIG9mIG91dHB1dCwgYWZ0ZXIgY29udHJvbGxpbmcgZm9yIGFnZSBhbmQgZ2VuZGVyLCBDT0FzIGFmZmlsaWF0ZSB3aXRoIGRldmlhbnQgcGVlcnMgYWJvdXQgLjM5MSBzdGFuZGFyZCBkZXZpYXRpb24gdW5pdHMgbW9yZSB0aGFuIG5vbi1DT0FzLiBFYWNoIGFkZGl0aW9uYWwgeWVhciBvZiBhZ2UgaXMgYXNzb2NpYXRlZCB3aXRoIGEgLjI4MSBzdGFuZGFyZCBkZXZpYXRpb24gaW5jcmVhc2UgaW4gc2VsZi1yZXBvcnRlZCBhZmZpbGlhdGlvbiB3aXRoIGRldmlhbnQgcGVlcnMuCgpGcm9tIHRoZSBSLXNxdWFyZSBvdXRwdXQsIHdlIGNhbiBzZWUgdGhhdCB0aGUgbXVsdGlwbGUgcHJlZGljdG9yIHJlZ3Jlc3Npb24gbW9kZWwgZXhwbGFpbnMgbW9yZSBvZiB0aGUgdmFyaWFuY2UgaW4gcGVlciB0aGFuIHRoZSBzaW5nbGUgcHJlZGljdG9yIG1vZGVsLiBBZ2UgYW5kIGdlbmRlciBhY2NvdW50IGZvciBhbiBhZGRpdGlvbmFsIDE3JSBvZiB0aGUgdmFyaWFuY2UgaW4gcGVlciwgb3ZlciBhbmQgYWJvdmUgQ09BIHN0YXR1cy4gU3RpbGwsIGFwcHJveGltYXRlbHkgKio4MCUgb2YgdGhlIHZhcmlhbmNlIGluIHBlZXIgcmVtYWlucyB1bmV4cGxhaW5lZCBieSB0aGUgdmFyaWFibGVzIGluIG91ciBtb2RlbCoqLgoKCgoKIyMjIyAxLjQgUGF0aCBBbmFseXNpcwoKIyMjIyMgMS40LjEgT3JpZ2luYWwgTW9kZWwKPHAgZmxvYXQ9ImxlZnQiPgogIDxpbWcgc3JjPSJmaWd1cmUvcGF0aC5qcGciIHdpZHRoPSI1MCUiIC8+CiAgPGltZyBzcmM9ImZpZ3VyZS9wYXRoMi5qcGciIHdpZHRoPSI0MCUiIC8+IAo8L3A+CgpUaGVvcnkgZGljdGF0ZXMgdGhhdCAqKmFsY29ob2xpYyBwYXJlbnRzKiogaW5jcmVhc2UgdGhlIG51bWJlciBvZiAqKnN0cmVzc2Z1bCBsaWZlIGV2ZW50cyoqIHRoYXQgdGhlaXIgY2hpbGRyZW4gZXhwZXJpZW5jZSwgbGVhZGluZyB0byBhbiBpbmNyZWFzZSBpbiBjaGlsZCAqKm5lZ2F0aXZlIGFmZmVjdCoqLiBGdXJ0aGVyLCBjaGlsZHJlbiBvZiBhbGNvaG9saWNzIGFyZSBoeXBvdGhlc2l6ZWQgdG8gaGF2ZSBoaWdoZXIgbGV2ZWxzIG9mIGVtb3Rpb25hbGl0eSwgbGVhZGluZyB0byBtb3JlIG5lZ2F0aXZlIGFmZmVjdC4gTmVnYXRpdmUgYWZmZWN0IGlzIHRob3VnaHQgdG8gYmUgcmVsYXRlZCB0byBoaWdoZXIgcmF0ZXMgb2YgKiphZmZpbGlhdGlvbuS7juWxnu+8jOWKoOebnyB3aXRoIGRldmlhbnQgcGVlcnMqKi4gU3RyZXNzZnVsIGxpZmUgZXZlbnRzIGFuZCBlbW90aW9uYWxpdHkgc2hvdWxkIGNvdmFyeSwgYnV0IHdlIGh5cG90aGVzaXplIG5vIGRpcmVjdGlvbmFsIHJlbGF0aW9uIGFtb25nIHRoZXNlIHZhcmlhYmxlcy4gV2UgYWxsb3cgYWdlIGFuZCBnZW4gdG8gcHJlZGljdCBzdHJlc3MgYW5kIGVtb3Rpb24sIGFuZCB3ZSBhbGxvdyBhbGwgZXhvZ2Vub3VzIGNoYXJhY3RlcmlzdGljcyAoY29hLCBnZW4sIGFuZCBhZ2UpIHRvIGNvdmFyeS4KPHAgZmxvYXQ9ImxlZnQiPgogIDxpbWcgc3JjPSJmaWd1cmUvcGF0aDMuanBnIiB3aWR0aD0iNDAlIiAvPgogIDxpbWcgc3JjPSJmaWd1cmUvcGF0aDQuanBnIiB3aWR0aD0iNTAlIiAvPiAKPC9wPgoKQXMgYSAqKmRlZmF1bHQqKiwgbGF2YWFuIGFsbG93cyBhbGwgZXhvZ2Vub3VzIHZhcmlhYmxlcyB0byBjb3ZhcnkgYnV0IGl0IGZpeGVzIHRoZSByZXNpZHVhbCAqKmNvdmFyaWFuY2VzIGFtb25nIGVuZG9nZW5vdXMgdmFyaWFibGVzIHRvIHplcm8qKi4gVGhlIHJlc2lkdWFsIHRlcm1zIG9mIHN0cmVzcyBhbmQgZW1vdGlvbiBhcmUgZnJlZWQgdG8gY292YXJ5IHdpdGhpbiB0aGUgc2VjdGlvbiBvZiB0aGUgY29kZSBtYXJrZWQgI2NvdmFyaWFuY2VzLiBUbyBkZXNpZ25hdGUgYSBjb3ZhcmlhbmNlIChvciB2YXJpYW5jZSkgd2UgdXNlIHRoZSB+fiBvcGVyYXRvci4gVGh1cywgKipzdHJlc3Mgfn4gZW1vdGlvbioqIHRlbGxzIGxhdmFhbiB0byBpbmNsdWRlIGEgcmVzaWR1YWwgY292YXJpYW5jZSBmb3Igc3RyZXNzIGFuZCBlbW90aW9uLgoKVGhlIGZpbmFsIHRocmVlIGxpbmVzIHJlcXVlc3QgdGhlICoqbW9kZWwtaW1wbGllZCBjb3ZhcmlhbmNlIG1hdHJpeCAoZml0dGVkKGZpdCkpKiogYW5kIHRoZSAqKnJhdyBhbmQgc3RhbmRhcmRpemVkIHJlc2lkdWFsIG1hdHJpY2VzKiogKHJlc2lkKGZpdCwgdHlwZT0icmF3IikgYW5kIHJlc2lkKGZpdCwgdHlwZT0ibm9ybWFsaXplZCIpLCByZXNwZWN0aXZlbHkpLiBUaGVzZSByZXNpZHVhbHMgcmVwcmVzZW50IHRoZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIHRoZSBvYnNlcnZlZCBjb3ZhcmlhbmNlIG1hdHJpeCBhbmQgdGhlIG1hdHJpeCB0aGF0IGlzIGltcGxpZWQgYnkgdGhlIHN0cnVjdHVyZSBvZiB0aGUgbW9kZWwuCmBgYHtyfQpwYXRobW9kZWwuMSA8LSAnCiAgICAgICAgICAgICAgI3JlZ3Jlc3Npb25zCiAgICAgICAgICAgICAgc3RyZXNzIH4gY29hICsgZ2VuICsgYWdlCiAgICAgICAgICAgICAgZW1vdGlvbiB+IGNvYSArIGdlbiArIGFnZQogICAgICAgICAgICAgIG5lZ2FmZiB+IHN0cmVzcyArIGVtb3Rpb24KICAgICAgICAgICAgICBwZWVyIH4gbmVnYWZmCgogICAgICAgICAgICAgICNjb3ZhcmlhbmNlcwogICAgICAgICAgICAgIHN0cmVzcyB+fiBlbW90aW9uICAgICAgICAgICAgICAKICAgICAgICAgICAgICAnCmZpdCA8LSBzZW0ocGF0aG1vZGVsLjEsIGRhdGE9YWZkcCwgbWVhbnN0cnVjdHVyZT1UUlVFKQpzdW1tYXJ5KGZpdCwgc3RhbmRhcmRpemVkPVRSVUUsIHJzcXVhcmU9VFJVRSkKYGBgCgpXZSByZXBvcnQgKipmdWxseSBzdGFuZGFyZGl6ZWQgZWZmZWN0cyoqIChmcm9tIFN0ZC5hbGwgY29sdW1uIGdlbmVyYXRlZCBieSB0aGUgZmlyc3Qgc3VtbWFyeSBmdW5jdGlvbiBjYWxsKSAqKmV4Y2VwdCBmb3IgY29hLCBnZW4sIGFuZCBhZ2UqKiwgZm9yIHdoaWNoIHdlIHJlcG9ydCBwYXJ0aWFsbHkgc3RhbmRhcmRpemVkIGVmZmVjdHMgKGZyb20gKipTdGQubm94KiogY29sdW1uIGdlbmVyYXRlZCBieSB0aGUgc2Vjb25kIHN1bW1hcnkgZnVuY3Rpb24gY2FsbCkuIFJlY2FsbCB0aGF0IG9ubHkgdGhlIG91dGNvbWUgdmFyaWFibGVzIGFyZSBzdGFuZGFyZGl6ZWQgaW4gY29tcHV0aW5nIHRoZSBwYXJ0aWFsbHkgc3RhbmRhcmRpemVkIGVmZmVjdHMsIHdoaWNoIG1ha2VzIHRoZW0gcGFydGljdWxhcmx5IHVzZWZ1bCBmb3IgZXhhbWluaW5nIHRoZSBlZmZlY3RzIG9mIGNvZGluZyB2YXJpYWJsZXMgKGUuZy4sIGNvYSBhbmQgZ2VuKSBvciBwcmVkaWN0b3JzIHdpdGggbmF0dXJhbCBtZXRyaWNzIChlLmcuLCBhZ2UpLgoKVGhlc2UgcGFydGlhbGx5IHN0YW5kYXJkaXplZCBwYXJhbWV0ZXIgZXN0aW1hdGVzIHJlcHJlc2VudCB0aGUgZXhwZWN0ZWQgY2hhbmdlIGluIHN0YW5kYXJkIGRldmlhdGlvbiB1bml0cyBpbiB5IGdpdmVuIGEgb25lIHVuaXQgaW5jcmVhc2UgaW4geC4gQnkgY29tcGFyaXNvbiwgdGhlIGZ1bGx5IHN0YW5kYXJkaXplZCBlc3RpbWF0ZXMgYXJlIGNvbXB1dGVkIGJ5IHN0YW5kYXJkaXppbmcgYm90aCB0aGUgcHJlZGljdG9ycyBhbmQgdGhlIG91dGNvbWUgdmFyaWFibGVzIHNvIHRoYXQgcGFyYW1ldGVyIGVzdGltYXRlcyByZXByZXNlbnQgdGhlIGV4cGVjdGVkIGNoYW5nZSBpbiBzdGFuZGFyZCBkZXZpYXRpb24gdW5pdHMgaW4geSBnaXZlbiBhIG9uZSBzdGFuZGFyZCBkZXZpYXRpb24gaW5jcmVhc2UgaW4geC4gVGhlc2UgYXJlIG1vc3QgdXNlZnVsIGZvciBpbnRlcnByZXRpbmcgZWZmZWN0cyB3aGVuIG5laXRoZXIgcHJlZGljdG9ycyBub3Igb3V0Y29tZXMgaGF2ZSBuYXR1cmFsIHNjYWxlcyBhbmQgd2hlbiBnYXVnaW5nIHJlbGF0aXZlIGVmZmVjdCBzaXplcyBhY3Jvc3MgcHJlZGljdG9ycyBvbiBkaWZmZXJlbnQgc2NhbGVzLiAqKkZvciBjb3ZhcmlhbmNlIHBhcmFtZXRlcnMsIGZ1bGx5IHN0YW5kYXJkaXplZCBlc3RpbWF0ZXMgY2FuIGJlIGludGVycHJldGVkIGFzIGNvcnJlbGF0aW9ucyoqLgoKRnJvbSB0aGUgUi1TcXVhcmUgc2VjdGlvbiBvZiBvdXRwdXQsIHdlIGNhbiBhbHNvIHNlZSB0aGF0IG9ubHkgYSBtb2Rlc3QgYW1vdW50IG9mIHRoZSB0b3RhbCB2YXJpYW5jZSBpbiBhbnkgb2YgdGhlc2UgdmFyaWFibGVzIGhhcyBiZWVuIGV4cGxhaW5lZCBieSB0aGUgbW9kZWwuCgpgYGB7cn0KcmVzaWQoZml0LCB0eXBlPSJub3JtYWxpemVkIikKYGBgCgpUaGUgbm9ybWFsaXplZCByZXNpZHVhbHMgYXJlIHJlc2NhbGVkIHRvIGZvbGxvdyBhIHN0YW5kYXJkIG5vcm1hbCBkaXN0cmlidXRpb24gYW5kIHZhbHVlcyBleGNlZWRpbmcgcGx1cyBvciBtaW51cyB0d28gYXJlIG9mdGVuIHRha2VuIGFzIHBvdGVudGlhbGx5IG1lYW5pbmdmdWwgaW4gbWFnbml0dWRlLiBUaGUgbm9ybWFsaXplZCByZXNpZHVhbHMgZm9yIHRoaXMgbW9kZWwgc3VnZ2VzdCB0aGF0IHRoZSBoeXBvdGhlc2l6ZWQgc3RydWN0dXJlIGlzIGRvaW5nIGEgKipwb29yKiogam9iICoqaW4gcmVwcm9kdWNpbmcqKiB0aGUgb2JzZXJ2ZWQgY292YXJpYW5jZXMgYmV0d2VlbiBzZXZlcmFsIHZhcmlhYmxlcywgbW9zdCBub3RhYmx5IGJldHdlZW4gKiphZ2UgYW5kIHBlZXIsIGJldHdlZW4gYWdlIGFuZCBuZWdhZmYsIGFuZCBiZXR3ZWVuIHN0cmVzcyBhbmQgcGVlcioqLiBXZSB3aWxsIGV4cGxvcmUgbWV0aG9kcyBmb3IgbW9yZSBmb3JtYWxseSBhc3Nlc3Npbmcgb3ZlcmFsbCBtb2RlbCBmaXQgaW4gdGhlIG5leHQgY2hhcHRlci4KCiMjIyMjIDEuNC4yIEV2YWx1YXRpb24gYW5kIHJlLXNwZWNpZmljYXRpb24KCldlIG9idGFpbiBtZWFzdXJlcyBvZiBmaXQsIGFwcHJvcHJpYXRlbHkgZW5vdWdoLCBieSBpbmNsdWRpbmcgKipmaXQubWVhc3VyZXM9VFJVRSoqCmBgYHtyfQpzdW1tYXJ5KGZpdCwgZml0Lm1lYXN1cmVzPVRSVUUpCmBgYAoKV2UgY2FuIHJlcXVlc3QgdGhhdCBsYXZhYW4gc3VnZ2VzdCBjaGFuZ2VzIHRvIG91ciBtb2RlbCBiYXNlZCBvbiB0aGUgZXhwZWN0ZWQgY2hhbmdlIGluIG1vZGVsIGNoaS1zcXVhcmUgaWYgYSBmaXhlZCBwYXJhbWV0ZXIgd2VyZSBmcmVlZDsgdGhlc2UgYXJlIHRoZSBtb2RpZmljYXRpb24gaW5kaWNlcyAoTUlzKS4gV2UgY2FuIG9idGFpbiBNSXMgd2l0aCB0aGUgbW9kaW5kaWNlcyBmdW5jdGlvbi4gVGhlIHNvcnQuIGFyZ3VtZW50IGlzIHNldCB0byBUUlVFIHNvIHRoYXQgbGF2YWFuIHdpbGwgcHJlc2VudCB0aGUgbGFyZ2VzdCBNSXMgZmlyc3QuIEFkZGl0aW9uYWxseSwgdGhlIG1pbmltdW0udmFsdWUgYXJndW1lbnQgaXMgc2V0IHRvIHN1cHByZXNzIHByaW50aW5nIG9mIGFueSBNSXMgbGVzcyB0aGFuIDEwLgoKYGBge3J9Cm1vZGluZGljZXMoZml0LCBzb3J0Lj1UUlVFLCBtaW5pbXVtLnZhbHVlPTEwKQpgYGAKSGVyZSwgbGhzIHN0YW5kcyBmb3Ig4oCcb24gdGhlIGxlZnQtaGFuZCBzaWRlIG9mIHRoZSBvcGVyYXRvcuKAnSBhbmQgcmhzIHN0YW5kcyBmb3Ig4oCcb24gdGhlIHJpZ2h0aGFuZCBzaWRlIG9mIHRoZSBvcGVyYXRvci7igJ0gVGhlIG9wZXJhdG9yLCBkZW5vdGVkIG9wLCBmb3IgdGhlc2UgcGFyYW1ldGVycyBpcyB+LCBpbmRpY2F0aW5nIHRoZXNlIGFyZSByZWdyZXNzaW9uIHNsb3Blcy4gKiptaSoqIGRlbm90ZXMgdGhlIGV4cGVjdGVkICoqaW1wcm92ZW1lbnQgaW4gdGhlIG1vZGVsIGNoaSBzcXVhcmUgdGVzdCBzdGF0aXN0aWMqKiBpZiB0aGUgbW9kaWZpY2F0aW9uIGlzIGFjY2VwdGVkLiBlcGMgZGVub3RlcyDigJxleHBlY3RlZCBwYXJhbWV0ZXIgY2hhbmdlIChFUEMp4oCdIGFuZCBnaXZlcyB0aGUgZXhwZWN0ZWQgcGFyYW1ldGVyIHZhbHVlIGlmIHRoZSBtb2RpZmljYXRpb24gaXMgaW1wbGVtZW50ZWQgKHNpbmNlIGl0IGlzIGNoYW5naW5nIGZyb20gemVybykuIHNlcGMubHYgcmUtc2NhbGVzIHRoZSBFUEMgYnkgc3RhbmRhcmRpemluZyBhbnkgbGF0ZW50IHZhcmlhYmxlcyBpbiB0aGUgbW9kZWwsIHNlcGMuYWxsIHJlLXNjYWxlcyB0aGUgRVBDIGJ5IHN0YW5kYXJkaXppbmcgYWxsIHZhcmlhYmxlcyAob2JzZXJ2ZWQgYW5kIGxhdGVudCksIGFuZCBzZXBjLm5veCByZS1zY2FsZXMgdGhlIEVQQyBieSBzdGFuZGFyZGl6aW5nIGFsbCB2YXJpYWJsZXMgZXhjZXB0IGV4b2dlbm91cyBwcmVkaWN0b3JzLiBIZXJlLCBzZXBjLmx2IGlzIGVxdWl2YWxlbnQgdG8gdGhlIEVQQyBiZWNhdXNlIHRoZXJlIGFyZSBubyBsYXRlbnQgdmFyaWFibGVzIGluIHRoZSBtb2RlbC4gSXQgY2FuIGJlIGhlbHBmdWwgdG8gcmVseSBvbiBzdGFuZGFyZGl6ZWQgRVBDIHZhbHVlcyBpbiBvcmRlciB0byBnZXQgYSBzZW5zZSBvZiB0aGUgcmVsYXRpdmUgbWFnbml0dWRlIG9mIGVhY2ggcG90ZW50aWFsIG1vZGlmaWNhdGlvbi4KCioqRmluYWwgTW9kZWwqKgoKIVtdKGZpZ3VyZS9wYXRoNS5qcGcpe3dpZHRoPTUwJX0KCmBgYHtyfQpwYXRobW9kZWwuNSA8LScKICAgICAgICAgICAgICAjcmVncmVzc2lvbnMKICAgICAgICAgICAgICBzdHJlc3MgfiBjb2EgKyBnZW4gKyBhZ2UKICAgICAgICAgICAgICBlbW90aW9uIH4gY29hICsgZ2VuICsgYWdlCiAgICAgICAgICAgICAgbmVnYWZmIH4gc3RyZXNzICsgZW1vdGlvbiArIGFnZQogICAgICAgICAgICAgIHBlZXIgfiBuZWdhZmYgKyBhZ2UgKyBjb2EKCiAgICAgICAgICAgICAgI2NvdmFyaWFuY2VzCiAgICAgICAgICAgICAgc3RyZXNzIH5+IGVtb3Rpb24gICAgICAgICAgICAgIAogICAgICAgICAgICAgICcKZml0LjUgPC0gc2VtKHBhdGhtb2RlbC41LCBkYXRhPWFmZHAsIG1lYW5zdHJ1Y3R1cmU9VFJVRSkKc3VtbWFyeShmaXQuNSwgZml0Lm1lYXN1cmVzPVRSVUUpCmBgYAoKIyMjIyMgMS40LjMgTWVkaWF0aW9uIFRlc3QKCk1lZGlhdG9yIGV4cGxhaW5zIHdoeSBvciBob3cgb25lIHZhcmlhYmxlIGV4ZXJ0cyBhbiBlZmZlY3Qgb24gYW5vdGhlci4gSW5kaXJlY3QgZWZmZWN0ICoqcG9pbnQgZXN0aW1hdGUqKiBpcyAqKnByb2R1Y3Qgb2YgY29lZmZpY2llbnRzKiogaW4gY2hhaW4uIHRoZSBDSSBpcyBjYWxjdWxhdGVkIGJ5ICoqZGVsdGEgbWV0aG9kKiogYW5kICoqYm9vdHN0cmFwcGluZyoqLgoKKipTaWduaWZpY2FudCBsaW5rcyBpbiBhIG1lZGlhdGlvbmFsIHBhdGh3YXkgYXJlIG5vdCBzdWZmaWNpZW50IHRvIGluZmVyIG1lZGlhdGlvbioqLiBJbiBvcmRlciB0byBmb3JtYWxseSB0ZXN0IHRoZSBmdWxsIG1lZGlhdGlvbiBlZmZlY3QsIHdlIG5lZWQgYW4gaW5mZXJlbnRpYWwgdGVzdCBvZiB0aGUgZW50aXJlIHNwZWNpZmljIGluZGlyZWN0IGVmZmVjdCBpbiBxdWVzdGlvbi4gSGVyZSwgd2Ugd2FudCB0byBrbm93IHdoZXRoZXIgdGhlIHNwZWNpZmljIG1lZGlhdGlvbmFsIHBhdGh3YXkgb2YgKipDT0Egc3RhdHVzIG9uIGRldmlhbnQgcGVlciBhZmZpbGlhdGlvbiB2aWEgc3RyZXNzZnVsIGV2ZW50cyBhbmQgbmVnYXRpdmUgYWZmZWN0KiogaXMgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCwgd2hldGhlciB0aGUgc3BlY2lmaWMgbWVkaWF0aW9uYWwgZWZmZWN0IG9mICoqY29hIG9uIHBlZXIgdmlhIGVtb3Rpb25hbGl0eSBhbmQgbmVnYXRpdmUgYWZmZWN0KiogaXMgc2lnbmlmaWNhbnQsIGFuZCB3aGV0aGVyIHRoZSAqKm92ZXJhbGwgaW5kaXJlY3QgZWZmZWN0IG9mIGNvYSBvbiBwZWVyKiogaXMgc2lnbmlmaWNhbnQuIEZpbmFsbHksIHdlIHdvdWxkIGxpa2UgdG8gaGF2ZSBhbiBlc3RpbWF0ZSBvZiB0aGUgKip0b3RhbCBlZmZlY3QqKiBvZiBjb2Egb24gcGVlciBjb25zaWRlcmluZyBib3RoIGRpcmVjdCBhbmQgaW5kaXJlY3QgcGF0aHdheXMuCgp3ZeKAmXZlIGFkZGVkICoqcGFyYW1ldGVyIGxhYmVscyoqIGZvciB0aGUgcGF0aHMgaW52b2x2ZWQgaW4gdGhlICoqZGlyZWN0IGFuZCBpbmRpcmVjdCBlZmZlY3RzIG9mIGNvYSBvbiBwZWVyKiouIEZvciBpbnN0YW5jZSwgaW4gdGhlIGxpbmUgc3RyZXNzIH4gY19zKmNvYSArIGdlbiArIGFnZSwgd2UgaGF2ZSBzdXBwbGllZCB0aGUgbGFiZWwgY19zIGZvciB0aGUgZWZmZWN0IG9mIGNvYSBvbiBzdHJlc3MuIExpa2V3aXNlLCB0aGUgb3RoZXIgcGF0aHMgaW52b2x2ZWQgaW4gY29tcHV0aW5nIHRoZSBlZmZlY3RzIG9mIGludGVyZXN0IGhhdmUgYWxzbyBiZWVuIGxhYmVsZWQuIFRvIGhlbHAga2VlcCB0cmFjayBvZiB0aGluZ3MsIG91ciBsYWJlbHMgY29uc2lzdCBvZiB0aGUgZmlyc3QgbGV0dGVyIG9mIHRoZSBwcmVkaWN0b3IsIGFuIHVuZGVyc2NvcmUsIGFuZCBmaXJzdCBsZXR0ZXIgb2Ygb3V0Y29tZSwgYnV0IGFueSBsYWJlbHMgYXJlIGZpbmUuIFdlIGNhbiBub3cgcmVmZXIgdG8gdGhlc2UgbGFiZWxzIHdoZW4gZGVmaW5pbmcgZGlyZWN0LCBpbmRpcmVjdCwgYW5kIHRvdGFsIGVmZmVjdHMuCgpGb2xsb3dpbmcgdGhlIGNvcmUgbW9kZWwgc3BlY2lmaWNhdGlvbiwgd2UgaGF2ZSBuZXcgbGluZXMgdG8gZGVmaW5lIHRoZSBkaXJlY3QsIHNwZWNpZmljIGluZGlyZWN0LCB0b3RhbCBpbmRpcmVjdCwgYW5kIHRvdGFsIGVmZmVjdHMuIFRoaXMgaXMgZG9uZSB1c2luZyB0aGUgKirigJxkZWZpbmXigJ0gb3BlcmF0b3IgOj0qKi4gRm9yIGluc3RhbmNlLCBpbmRfcyA6PSBjX3Mqc19uKm5fcCByZXF1ZXN0cyB0aGF0IGxhdnZhbiBjb21wdXRlIHRoZSBxdWFudGl0eSBpbmRfcyBhcyB0aGUgcHJvZHVjdCBvZiB0aGUgdGhyZWUgcGF0aHMgcHJldmlvdXNseSBsYWJlbGVkIGNfcywgc19uLCBhbmQgbl9wLgoKYGBge3J9CmVmZmVjdHMuNSA8LScKICAgICAgICAgICAgI3JlZ3Jlc3Npb25zCiAgICAgICAgICAgIHN0cmVzcyB+IGNfcypjb2EgKyBnZW4gKyBhZ2UKICAgICAgICAgICAgZW1vdGlvbiB+IGNfZSpjb2EgKyBnZW4gKyBhZ2UKICAgICAgICAgICAgbmVnYWZmIH4gc19uKnN0cmVzcyArIGVfbiplbW90aW9uICsgYWdlCiAgICAgICAgICAgIHBlZXIgfiBuX3AqbmVnYWZmICsgYWdlICsgY19wKmNvYSAKCiAgICAgICAgICAgICNjb3ZhcmlhbmNlcwogICAgICAgICAgICBzdHJlc3Mgfn4gZW1vdGlvbiAgICAgICAgIAoKICAgICAgICAgICAgI2RpcmVjdCBlZmZlY3QKICAgICAgICAgICAgZGlyIDo9IGNfcAoKICAgICAgICAgICAgI3NwZWNpZmljIGluZGlyZWN0IGVmZmVjdHMKICAgICAgICAgICAgaW5kX3MgOj0gY19zKnNfbipuX3AKICAgICAgICAgICAgaW5kX2UgOj0gY19lKmVfbipuX3AKCiAgICAgICAgICAgICN0b3RhbCBpbmRpcmVjdCBlZmZlY3QKICAgICAgICAgICAgdG90X2luZCA6PSBjX3Mqc19uKm5fcCArIGNfZSplX24qbl9wCgogICAgICAgICAgICAjdG90YWwgZWZmZWN0CiAgICAgICAgICAgIHRvdCA6PSBjX3Mqc19uKm5fcCArIGNfZSplX24qbl9wICsgY19wCiAgICAgICAgICAgICcKc2V0LnNlZWQoNjI5NzMpCmZpdC41YiA8LSBzZW0oZWZmZWN0cy41LCBkYXRhPWFmZHAsIG1lYW5zdHJ1Y3R1cmU9VFJVRSwgc2U9ImJvb3RzdHJhcCIsIGJvb3RzdHJhcD0xMDAwKQpgYGAKCk5vdGUgdGhhdCB3ZSBoYXZlIHVzZWQgdGhlIHNldC5zZWVkIGZ1bmN0aW9uIHRvIHNldCB0aGUgcmFuZG9tIG51bWJlciBzZWVkIGZvciBzZWxlY3RpbmcgdGhlIGJvb3RzdHJhcHBlZCBzYW1wbGVzIHNvIHRoYXQgd2UgY2FuIHJlcHJvZHVjZSBleGFjdGx5IHRoZXNlIHNhbWUgcmVzdWx0cyBlYWNoIHRpbWUgd2UgcnVuIHRoZSBzY3JpcHQuCgpUaGVuLCBpbiB0aGUgc2VtIGZ1bmN0aW9uLCB3ZSBzcGVjaWZpZWQgc2U9ImJvb3RzdHJhcCIsIGJvb3RzdHJhcD0xMDAwIHRvIHJlcXVlc3QgdGhhdCBsYXZhYW4gY29tcHV0ZSAqKmJvb3RzdHJhcHBlZCBzdGFuZGFyZCBlcnJvcnMqKiB3aXRoIDEwMDAgYm9vdHN0cmFwcGVkIHNhbXBsZXMuIFdlIGFjdHVhbGx5IGRvbuKAmXQgY2FyZSBtdWNoIGFib3V0IHRoZSBzdGFuZGFyZCBlcnJvcnMuIFdoYXQgd2UgcmVhbGx5IHdhbnQgYXJlIGJvb3RzdHJhcHBlZCBjb25maWRlbmNlIGludGVydmFscywgd2hpY2ggYXJlIGdlbmVyYXRlZCBpbiB0aGUgcGFyYW1ldGVyRXN0aW1hdGVzIGZ1bmN0aW9uIHdpdGggdGhlIGJvb3QuY2kudHlwZSBhcmd1bWVudC4gVGhlIHBhcmFtZXRlckVzdGltYXRlcyBmdW5jdGlvbiBwcm9kdWNlcyBhIHNpbXBsZSBsaXN0IG9mIHRoZSBwYXJhbWV0ZXIgZXN0aW1hdGVzIGZyb20gdGhlIG1vZGVsLiBCeSBpbmNsdWRpbmcgdGhlIGJvb3QuY2kudHlwZSBhcmd1bWVudCwgd2UgcmVxdWVzdCB0aGF0IHRoaXMgb3V0cHV0IGluY2x1ZGUgOTUlIGJvb3N0cmFwcGVkIGNvbmZpZGVuY2UgaW50ZXJ2YWxzLgoKTm90ZSB0aGF0IHRoZXJlIGV4aXN0ICoqbXVsdGlwbGUgbWV0aG9kcyoqIGZvciBjYWxjdWxhdGluZyAqKmJvb3RyYXBwZWQgQ0lzKiouIFRoZSAqKnBlcmNlbnRpbGUqKiBtZXRob2QgaXMgcHJvYmFibHkgZWFzaWVzdCB0byB1bmRlcnN0YW5kIOKAkyB0aGUgMTAwMCBib29zdHJhcHBlZCBlc3RpbWF0ZXMgYXJlIG9yZGVyZWQgYnkgbWFnbml0dWRlIGFuZCB0aGUgMjUgdGggZXN0aW1hdGUgKDIuNSB0aCBwZXJjZW50aWxlKSBhbmQgOTc1IHRoIGVzdGltYXRlICg5Ny41IHRoIHBlcmNlbnRpbGUpIGFyZSB0YWtlbiBhcyB0aGUgY29uZmlkZW5jZSBsaW1pdHMsIHlpZWxkaW5nIGEgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWwuIFRoaXMgbWV0aG9kLCB3aGljaCBpcyB3aWRlbHkgYXZhaWxhYmxlIGluIG1hbnkgc29mdHdhcmUgcHJvZ3JhbXMsIGlzIG9idGFpbmVkIHZpYSBib290LmNpLnR5cGUgPSAicGVyYyIuIFRoYXQgaXMgdGhlIG1ldGhvZCB3ZSB1c2VkIGluIHRoZSBsZWN0dXJlIG5vdGVzLiBBIHNsaWdodGx5IHByZWZlcmFibGUgYXBwcm9hY2gsIGhvd2V2ZXIsIGlzIHRvIHVzZSBiaWFzLWNvcnJlY3RlZCBib290c3RyYXBwZWQgY29uZmlkZW5jZSBpbnRlcnZhbHMsIGFuZCB0aGVzZSBhcmUgcmVhZGlseSBhdmFpbGFibGUgaW4gbGF2YWFuLiBUbyBvYnRhaW4gdGhlICoqYmlhcyBjb3JyZWN0ZWQqKiBjb25maWRlbmNlIGludGVydmFscywgd2Ugc2ltcGx5IHVzZSBib290LmNpLnR5cGUgPSAiYmNhLnNpbXBsZSIuIFRoZSBiaWFzY29ycmVjdGVkIGludGVydmFscyBhcmUgc2hvd24gaW4gdGhlIG91dHB1dCBiZWxvdy4gSW4gdGVybXMgb2YgbnVsbCBoeXBvdGhlc2lzIHRlc3RpbmcsIHRoZSBzYW1lIGNvbmNsdXNpb25zIGFyZSBnZW5lcmF0ZWQgd2l0aCB0aGUgYmlhcy1jb3JyZWN0ZWQgQ0lzIGFzIHdpdGggdGhlIHBlcmNlbnRpbGUgQ0lzIHByZXNlbnRlZCBpbiBsZWN0dXJlLCBidXQgdGhlcmUgYXJlIHNvbWUgc2xpZ2h0IGRpZmZlcmVuY2VzIGluIHRoZSBzcGVjaWZpYyB2YWx1ZXMgb2YgdGhlIGNvbmZpZGVuY2UgbGltaXRzLgpgYGB7cn0KcGFyYW1ldGVyRXN0aW1hdGVzKGZpdC41YiwgYm9vdC5jaS50eXBlID0gInBlcmMiKQpwYXJhbWV0ZXJFc3RpbWF0ZXMoZml0LjViLCBib290LmNpLnR5cGUgPSAiYmNhLnNpbXBsZSIpCmBgYAoKVGhlIHRvdGFsIGVmZmVjdCBvZiBjb2Egb24gcGVlciBpcyBlcXVhbCB0byAuMjA5IGFuZCByZXByZXNlbnRzIGEgY29tYmluYXRpb24gb2YgdGhlIGRpcmVjdCBlZmZlY3QgKC4xODUpIGFuZCB0aGUgdG90YWwgaW5kaXJlY3QgZWZmZWN0ICguMDI0KS4gVGhlIDk1JSBDSSBpcyBlcXVhbCB0byAuMDk0IGFuZCAuMzA2OyBiZWNhdXNlIHRoaXMgZG9lcyBub3QgY29udGFpbiB6ZXJvLCB0aGUgdG90YWwgZWZmZWN0IGlzIGRlZW1lZCB0byBiZSBzaWduaWZpY2FudC4KCkV4YW1pbmluZyB0aGUgbWVkaWF0aW9uYWwgcGF0aHdheXMsIHdlIHNlZSB0aGF0IHRoZSBzcGVjaWZpYyBpbmRpcmVjdCBlZmZlY3QgY29h4oaSc3RyZXNz4oaSbmVnYWZm4oaScGVlciwgbGFiZWxlZCAqKmluZF9zKiogdG8gaW5kaWNhdGUgaXQgaXMgdGhlIGluZGlyZWN0IGVmZmVjdCB0aHJvdWdoIHN0cmVzcywgaXMgZXF1YWwgdG8gLjAxNSAoOTUlIENJPS4wMDUsIC4wMzYpIGFuZCBpcyAqKnNpZ25pZmljYW50KiogKGRvZXMgbm90IGluY2x1ZGUgemVybykuIFRoZSBiaW9sb2dpY2FsIHBhdGh3YXkgZnJvbSBjb2HihpJlbW90aW9u4oaSbmVnYWZm4oaScGVlciwgbGFiZWxlZCAqKmluZF9lKiogdG8gaW5kaWNhdGUgaXQgaXMgdGhlIGluZGlyZWN0IGVmZmVjdCB0aHJvdWdoIGVtb3Rpb24sIGlzIGVxdWFsIHRvIC4wMDkgKDk1JSBDST0wLCAuMDIyKSBhbmQgdGh1cyBkb2VzICoqbm90IHJlYWNoIHN0YXRpc3RpY2FsIHNpZ25pZmljYW5jZSoqIChiZWNhdXNlIHRoZSBsb3dlciBDSSBpcyBlcXVhbCB0byB6ZXJvKS4KCgojIyMgMi4gRmFjdG9yIEFuYWx5c2lzCiMjIyMgRUZBCioqTGF0ZW50IHZhcmlhYmxlIGFsc28gY2FsbGVkKio6IHVubWVhc3VyZWQgdmFyaWFibGVzLCBjb25zdHJ1Y3RzLCBmYWN0b3JzLCB0cnVlIHNjb3JlcywgdW5vYnNlcnZlZCB2YXJpYWJsZXMsIHVub2JzZXJ2ZWQgaGV0ZXJvZ2VuZWl0eS4gTGF0ZW50IHZhcmlhYmxlIGlzICoqdXNlZCBmb3IqKjogZmFjdG9ycyBpbiBmYWN0b3IgYW5hbHlzaXMsIGxhdGVudCB2YXJpYWJsZXMgaW4gc3RydWN0dXJhbCBlcXVhdGlvbiBtb2RlbHMsIGJhc2lzIGN1cnZlcyBpbiBsYXRlbnQgY3VydmUgYW5hbHlzaXMsIGxhdGVudCBjbGFzc2VzIChjbGFzcy9jbHVzdGVyL21peHR1cmUgbW9kZWxzKSwgbGF0ZW50IHRyYWl0cywgdW5kZXJseWluZyBwcm9wZW5zaXR5IHZhcmlhYmxlcyBmb3IgY2Vuc29yZWQvbGltaXRlZCBkZXBlbmRlbnQgdmFyaWFibGVzLCBtaXNzaW5nIGRhdGEsICoqcmFuZG9tIGVmZmVjdHMgaW4gYSBtdWx0aWxldmVsIG9yIG1peGVkIG1vZGVsKiouCgpHb2FscyBvZiBGYWN0b3IgQW5hbHlzaXM6IGRldGVybWluZSB0aGUgdW5kZXJseWluZyBzdHJ1Y3R1cmUgYmVoaW5kIGEgc2V0IG9mIG9ic2VydmVkIG1lYXN1cmVzLgoKRXhwbG9yYXRvcnkgZmFjdG9yIGFuYWx5c2lzIGlzIHByaW1hcmlseSBkYXRhLWRyaXZlbjogKiphbGwgb2JzZXJ2ZWQgdmFyaWFibGVzIHJlZ3Jlc3NlZCBvbiBhbGwgZmFjdG9ycyoqIGFuZCB0aGUgcmVncmVzc2lvbiBzbG9wZXMuIENvbmZpcm1hdG9yeSBmYWN0b3J5IGFuYWx5c2lzIGlzIGZvcm1hbGx5IHRlc3RpbmcgYSB0aGVvcmV0aWNhbCBmYWN0b3Igc3RydWN0dXJlLCBudW1iZXIgYW5kIG5hdHVyZSBvZiBsYXRlbnQgdmFyaWFibGVzIHNwZWNpZmllZCBieSB0aGVvcnksIHJlbGF0aW9uc2hpcHMgYmV0d2VlbiBpbmRpY2F0b3JzIGFuZCBsYXRlbnQgdmFyaWFibGVzIHNwZWNpZmllZCBieSB0aGVvcnkuCgoqKk91dGNvbWUgdmFyaWFibGUgaXMgcmVncmVzc2VkIG9uIHRoZSBwcmVkaWN0b3JzLioqIEFzIHRoZSB0YXJnZXQgcHJlZGljdGVkIG91dGNvbWUgeSBkZXBlbmRzIG9uIHRoZSBwcmVkaWN0b3IgeCwgeW91IGNhbiBzYXkgdGhhdCAiaXMgcmVncmVzc2VkIG9uIiBtZWFucyAiaXMgZGVwZW5kZW50IG9uIi4gVGhlIHdvcmQgInJlZ3Jlc3NlZCIgaXMgdXNlZCBpbnN0ZWFkIG9mICJkZXBlbmRlbnQiIGJlY2F1c2Ugd2Ugd2FudCB0byBlbXBoYXNpc2UgdGhhdCB3ZSBhcmUgdXNpbmcgYSByZWdyZXNzaW9uIHRlY2huaXF1ZSB0byByZXByZXNlbnQgdGhpcyBkZXBlbmRlbmN5IGJldHdlZW4geCBhbmQgeS4KCiFbXShmaWd1cmUvRUZBMy5qcGcpe3dpZHRoPTUwJX0KIVtdKGZpZ3VyZS9FRkEyLmpwZyl7d2lkdGg9NDAlfQoKJFxUaGV0YSQgaXMgcmVzaWR1YWwgY292YXJpYW5jZSBtYXRyaXgKCioqQ29tbXVuYWxpdHkqKi4gJFJeMiQgZm9yIHJlZ3Jlc3Npb24gb2YgdGhlIGluZGljYXRvciBvbiB0aGUgc2V0IG9mIGNvbW1vbiBmYWN0b3JzOiBpdGVtcyB3aXRoIGhpZ2ggY29tbXVuYWxpdGllcyBhcmUgZ29vZCBpdGVtcywgYXMgbW9zdCBvZiB0aGVpciB2YXJpYW5jZSByZWZsZWN0cyB0aGUgaW5mbHVlbmNlIG9mIHRoZSBjb21tb24gZmFjdG9ycwokJApoXjI9MS1cZnJhY3tWQVIoXHZhcmVwc2lsb24pfXtWQVIoeSl9CiQkCgpDb25kdWN0aW5nIFByb2Nlc3MKCjEuIERldGVybWluZSBudW1iZXIgb2YgbGF0ZW50IGZhY3RvcnMKMi4gUm90YXRlIGZhY3RvciBwYXR0ZXJuIG1hdHJpeCBhdCBjaG9zZW4gbnVtYmVyIG9mIGZhY3RvcnMKMy4gRWxpbWluYXRlIHByb2JsZW1hdGljIGl0ZW1zIGFuZCByZWZpdCBtb2RlbCAoaXRlbXMgd2l0aCBsYXJnZSBjcm9zcy1sb2FkaW5ncyBvciB3aXRoIGxvdyBjb21tdW5hbGl0aWVzLCByZWR1bmRhbnQgaXRtZXMgb3RoZXJ3aXNlIG1heSBoaWphY2sgdGhlIGZhY3RvcikKNC4gSW5zcGVjdCBmaW5hbCBwYXR0ZXJuIG1hdHJpeCB0byBkZXRlcm1pbmUgbWVhbmluZyBvZiBsYXRlbnQgZmFjdG9ycwoKIyMjIyBDRkEKCiFbXShmaWd1cmUvQ0ZBMS5qcGcpe3dpZHRoPTMwJX0gIVtdKGZpZ3VyZS9DRkEyLmpwZyl7d2lkdGg9MzAlfSAhW10oZmlndXJlL0NGQTMuanBnKXt3aWR0aD0zMCV9CgpTZXR0aW5nIHRoZSBzY2FsZSBvZiBsYXRlbmV0IHZhcmlhYmxlcwoKMS4gc2V0IG1lYW5zIGFuZCB2YXJpYW5jZXMgb2YgdGhlIGxhdGVudCB2YXJpYWJsZXMgdG8gemVybyBhbmQgb25lCiAgICArIHB1dHMgbGF0ZW50IHZhcmlhYmxlcyBvbiBhIHN0YW5kYXJkaXplZCBzY2FsZQogICAgKyBhbGxvd3MgZm9yIGVzdGltYXRpb24gb2YgYWxsIGZhY3RvciBsb2FkaW5ncyAoYW5kIGludGVyY2VwdHMpCiAgICArIHNhbWUgbG9hZGluZyBzY2FsaW5nIG9wdGlvbiB0aGF0IGlzIHVzZWQgaW4gRUZBCgoyLiBnaXZlIGVhY2ggbGF0ZW50IHZhcmlhYmxlIHRoZSBzYW1lIG1ldHJpYyBhcyBvbmUgb2YgdGhlIG9ic2VydmVkIHZhcmlhYmxlcy4gVGhlIGludGVyY2VwdCBhbmQgbG9hZGluZyBmb3IgdGhlICJzY2FsaW5nIGl0ZW0iIGFyZSBzZXQgdG8gemVybyBhbmQgb25lCgpDRkEgRXhhbXBsZSBkYXRhc2V0IGRlc2NyaXB0aW9uLS0tClRoZSBkYXRhIGZvciB0aGlzIGRlbW9uc3RyYXRpb24gd2VyZSBwcm92aWRlZCBieSBIb2x6aW5nZXIgJiBTd2luZWZvcmQgaW4gdGhlaXIgMTkzOSBtb25vZ3JhcGggQSBTdHVkeSBpbiBGYWN0b3IgQW5hbHlzaXM6IFRoZSBTdGFiaWxpdHkgb2YgYSBCaS1GYWN0b3IgU29sdXRpb24uIFRoZSBzYW1wbGUgaW5jbHVkZXMgMzAxIDd0aCBhbmQgOHRoIGdyYWRlIHN0dWRlbnRzLCBiZXR3ZWVuIDExLTE2IHllYXJzIG9mIGFnZSwgZHJhd24gZnJvbSB0d28gc2Nob29scy4gVGhlIGRhdGEgaXMgaW4gdGhlIHRleHQgZmlsZSBocy5kYXQgYW5kIHRoZSBhY2NvbXBhbnlpbmcgUi1zY3JpcHQgZmlsZSBpcyBjaDA0LlIuIFRoZSB2YXJpYWJsZXMgaW4gdGhlIGRhdGEgc2V0IHRoYXQgd2Ugd2lsbCB1c2UgYXJlCgp2aXNwZXJjIHZpc3VhbCBwZXJjZXB0aW9uIHRlc3QgaW4gd2hpY2ggcGFydGljaXBhbnRzIHNlbGVjdCB0aGUgbmV4dCBpbWFnZSBpbiBhIHNlcmllcwoKY3ViZXMgIHZpc3VhbCBwZXJjZXB0aW9uIHRlc3QgaW4gd2hpY2ggcGFydGljaXBhbnRzIG11c3QgbWVudGFsbHkgcm90YXRlIGEgY3ViZQoKbG96ZW5nZXMgIHZpc3VhbCBwZXJjZXB0aW9uIHRlc3QgaW52b2x2aW5nIG1lbnRhbCDigJxmbGlwcGluZ+KAnSBvZiBhIHBhcmFsbGVsb2dyYW0gKOKAnGxvemVuZ2XigJ0pCgpwYXJjb21wICBwYXJhZ3JhcGggY29tcHJlaGVuc2lvbiB0ZXN0CgpzZW5jb21wIHNlbnRlbmNlIGNvbXBsZXRpb24gdGFzayBpbiB3aGljaCBwYXJ0aWNpcGFudHMgc2VsZWN0IG1vc3QgYXBwcm9wcmlhdGUgd29yZCB0byBwdXQgYXQgdGhlIGVuZCBvZiBhIHNlbnRlbmNlCgp3b3JkbWVhbiB2ZXJiYWwgYWJpbGl0eSB0ZXN0IGluIHdoaWNoIHBhcnRpY2lwYW50cyBtdXN0IHNlbGVjdCBhIHdvcmQgbW9zdCBzaW1pbGFyIGluIG1lYW5pbmcgdG8gYSB3b3JkIHVzZWQgaW4gYSBzZW50ZW5jZS4KCmFkZGl0aW9uIHBhcnRpY2lwYW50cyBoYXZlIDIgbWludXRlcyB0byBjb21wbGV0ZSBhcyBtYW55IDItbnVtYmVyIGFkZGl0aW9uIHByb2JsZW1zIGFzIHRoZXkgY2FuCgpjb3VudGRvdCBwYXJ0aWNpcGFudHMgaGF2ZSA0IG1pbnV0ZXMgdG8gY291bnQgdGhlIG51bWJlciBvZiBkb3RzIGluIGVhY2ggb2YgYSBzZXJpZXMgb2YgZG90IHBpY3R1cmVzCgpzY2NhcHMgcGFydGljaXBhbnRzIGhhdmUgMyBtaW51dGVzIHRvIGluZGljYXRlIHdoZXRoZXIgY2FwaXRhbCBsZXR0ZXJzIGFyZSBjb21wb3NlZCBlbnRpcmVseSBvZiBzdHJhaWdodCBsaW5lcyBvciBpbmNsdWRlIGN1cnZlZCBsaW5lcy4KCk90aGVyIHZhcmlhYmxlcyBpbiB0aGUgZGF0YSBub3QgaW5jbHVkZWQgaW4gdGhlIG1vZGVscyBmaXQgaGVyZSBhcmUgc2Nob29sLCBmZW1hbGUsIGFnZSwgYW5kIG1vbnRoLgoKYGBge3J9CmhzIDwtIHJlYWQudGFibGUoImRhdGEvaHMuZGF0IiwgaGVhZGVyPUZBTFNFKSAKCm5hbWVzKGhzKSA8LSBjKCJzY2hvb2wiLCAiZmVtYWxlIiwgImFnZSIsICJtb250aCIsICJ2aXNwZXJjIiwgImN1YmVzIiwgImxvemVuZ2VzIiwgInBhcmNvbXAiLCAic2VuY29tcCIsICJ3b3JkbWVhbiIsICJhZGRpdGlvbiIsICJjb3VudGRvdCIsICJzY2NhcHMiKQpgYGAKCnJlc2NhbGVkIHRoZSB2YXJpYWJsZXMgYWRkaXRpb24sIGNvdW50ZG90LCBhbmQgc2NjYXBzIGJ5IGRpdmlkaW5nIGJ5IGZvdXI6IFRoaXMgd2FzIGRvbmUgdG8gZmFjaWxpdGF0ZSBtb2RlbCBlc3RpbWF0aW9uLCBhcyBudW1lcmljYWwgaW5zdGFiaWxpdHkgcHJvYmxlbXMgY2FuIGFyaXNlIHdoZW4gdXNpbmcgdmFyaWFibGVzIG9uIHdpZGVseSBkaWZmZXJpbmcgc2NhbGVzLiBEaXZpZGluZyB0aGVzZSB2YXJpYWJsZXMgYnkgZm91ciBicmluZ3MgdGhlaXIgc3RhbmRhcmQgZGV2aWF0aW9ucyBjbG9zZXIgdG8gdGhlIHN0YW5kYXJkIGRldmlhdGlvbnMgb2YgdGhlIG90aGVyIG9ic2VydmVkIHZhcmlhYmxlcy4KCmBgYHtyfQpocyRhZGRpdGlvbiA8LSBocyRhZGRpdGlvbi80IApocyRjb3VudGRvdCA8LSBocyRjb3VudGRvdC80IApocyRzY2NhcHMgPC0gaHMkc2NjYXBzLzQKYGBgCgpGaW5hbGx5LCB3ZSBsb2FkIHRoZSBsYXZhYW4gcGFja2FnZSB0aGF0IHdlIHdpbGwgdXNlIHRvIGZpdCB0aGUgQ0ZBIG1vZGVsczoKCiFbXShmaWd1cmUvQ0ZBX2VnLmpwZyl7d2lkdGg9NDAlfSAKCmNmYSBmdW5jdGlvbiBpbiBsYXZhYW4gaW1wb3NlcyBhIG51bWJlciBvZiBkZWZhdWx0cyBjb25zaXN0ZW50IHdpdGggaG93IENGQSBtb2RlbHMgYXJlIHR5cGljYWxseSBzcGVjaWZpZWQgYW5kIGVuYWJsZXMgdXMgdG8gc3BlY2lmeSBtb2RlbHMgd2l0aCBjb21wYWN0IG1vZGVsIHN5bnRheCBvYmplY3RzLiBUaGUgZGVmYXVsdCBzY2FsaW5nIGZvciB0aGUgbGF0ZW50IHZhcmlhYmxlcyBpcyBhIGh5YnJpZCBvZiB0aGUgYXBwcm9hY2hlcyB3ZSBkZXNjcmliZWQgaW4gbGVjdHVyZS4gVGhlIGRlZmF1bHQgc2NhbGluZyBmb3IgdGhlIGxhdGVudCB2YXJpYWJsZXMgaXMgYSBoeWJyaWQgb2YgdGhlIGFwcHJvYWNoZXMgd2UgZGVzY3JpYmVkIGluIGxlY3R1cmUuIEJ5IGRlZmF1bHQsIHRoZSAqKmxhdGVudCB2YXJpYWJsZXMgd2lsbCBoYXZlIG1lYW5zIHNldCB0byB6ZXJvKiogYnV0IGZyZWVseSBlc3RpbWF0ZWQgdmFyaWFuY2UuIEFkZGl0aW9uYWxseSwgdGhlICoqZmFjdG9yIGxvYWRpbmcgb2YgdGhlIGZpcnN0IGluZGljYXRvciBmb3IgZWFjaCBsYXRlbnQgdmFyaWFibGUgd2lsbCBiZSBzZXQgdG8gb25lKiogYnV0IHRoZSBpbnRlcmNlcHQgZm9yIHRoaXMgaW5kaWNhdG9yIHdpbGwgYmUgZnJlZWx5IGVzdGltYXRlZC4gV2Ugd2lsbCBvdmVycmlkZSB0aGVzZSBkZWZhdWx0cyB0byBpbXBsZW1lbnQgdGhlIHNjYWxpbmcgb3B0aW9ucyBkZXNjcmliZWQgaW4gbGVjdHVyZS4gaW4gZGVmaW5pbmcgdGhlIG1vZGVsIHN5bnRheCBvYmplY3QsIHdlIGltcGxlbWVudCB0aGUgPX4gb3BlcmF0b3IsIHdoaWNoIGlzIHVzZWQgdG8gZGVmaW5lIGxhdGVudCB2YXJpYWJsZXMgKGxlZnQgaGFuZCBzaWRlKSBhbmQgdG8gc3BlY2lmeSB0aGUgdmFyaWFibGVzIHRoYXQgbG9hZCBvbiB0aGVtIChyaWdodCBoYW5kIHNpZGUpLiBUaHVzLCB2aXN1YWwgPX4gdmlzcGVyYyArIGN1YmVzICsgbG96ZW5nZXMgZGVmaW5lcyBhIG5ldyBsYXRlbnQgdmFyaWFibGUsIHZpc3VhbCwgYW5kIGluZGljYXRlcyB0aGF0IHZpc3BlcmMsIGN1YmVzLCBhbmQgbG96ZW5nZXMgYXJlIGluZGljYXRvciB2YXJpYWJsZXMuCgpgYGB7cn0KY2ZhLjFhIDwtJyNmYWN0b3IgbG9hZGluZ3MKICAgICAgICAgIHZpc3VhbCA9fiB2aXNwZXJjICsgY3ViZXMgKyBsb3plbmdlcwogICAgICAgICAgdmVyYmFsID1+IHBhcmNvbXAgKyBzZW5jb21wICsgd29yZG1lYW4KICAgICAgICAgIHNwZWVkID1+IGFkZGl0aW9uICsgY291bnRkb3QgKyBzY2NhcHMKICAgICAgICAgJwoKZml0LjFhIDwtIGNmYShjZmEuMWEsIGRhdGE9aHMsIG1lYW5zdHJ1Y3R1cmU9VFJVRSwgc3RkLmx2PVRSVUUpCnN1bW1hcnkoZml0LjFhLCBmaXQubWVhc3VyZXM9VFJVRSwgc3RhbmRhcmRpemVkPVRSVUUsIHJzcXVhcmU9VFJVRSkKYGBgClRoZSBtb2RpZmljYXRpb24gaW5kaWNlcyBmb3IgdGhlIG1vZGVsIGFyZSBvYnRhaW5lZCBmcm9tIHRoZSBtb2RpbmRpY2VzIGZ1bmN0aW9uIGFzIGZvbGxvd3M6CmBgYHtyfQptb2RpbmRpY2VzKGZpdC4xYSwgc29ydC49VFJVRSwgbWluaW11bS52YWx1ZT0xMCkKYGBgCgpIZXJlIHdlIHNlZSB0aGUgbGFyZ2VzdCBtb2RpZmljYXRpb24gaW5kaWNlcyBhcmUgYXNzb2NpYXRlZCB3aXRoIGEgY3Jvc3MtbG9hZGluZyBmb3Igc2NjYXBzIG9uIHZpc3VhbCwgYW5kIGEgY29ycmVsYXRlZCB1bmlxdWVuZXNzIGZvciBjb3VudGRvdCB3aXRoIGFkZGl0aW9uLiBJdCBpcyBpbXBvcnRhbnQgdG8ga2VlcCBpbiBtaW5kIHRoYXQgYm90aCBtb2RpZmljYXRpb24gaW5kaWNlcyBtYXkgYmUgcmVsYXRlZCB0byB0aGUgc2FtZSBtaXNzcGVjaWZpY2F0aW9uLgoKCkluaXRpYWwgTW9kZWwgd2l0aCBTY2FsaW5nIEl0ZW1zOiBtb2RlbCBmaXQgaXMgdGhlIHNhbWUKCldlIHNoYWxsIGNob29zZSB0aGUgZmlyc3QgaW5kaWNhdG9yIGZvciBlYWNoIGZhY3RvciB0byBiZSB0aGUgc2NhbGluZyBpdGVtLiBUaGUgaW50ZXJjZXB0IGFuZCBmYWN0b3IgbG9hZGluZyBmb3IgZWFjaCBzY2FsaW5nIGl0ZW0gaXMgc2V0IHRvIHplcm8gYW5kIG9uZSwgcmVzcGVjdGl2ZWx5LiBUaGlzIHNjYWxpbmcgb3B0aW9uIHBlcm1pdHMgdGhlIG1lYW5zIGFuZCB2YXJpYW5jZXMgb2YgdGhlIGxhdGVudCBmYWN0b3JzIHRvIGJlIGVzdGltYXRlZC4KCgpgYGB7cn0KY2ZhLjFiIDwtJyNmYWN0b3IgbG9hZGluZ3MKICAgICAgICAgIHZpc3VhbCA9fiB2aXNwZXJjICsgY3ViZXMgKyBsb3plbmdlcwogICAgICAgICAgdmVyYmFsID1+IHBhcmNvbXAgKyBzZW5jb21wICsgd29yZG1lYW4KICAgICAgICAgIHNwZWVkID1+IGFkZGl0aW9uICsgY291bnRkb3QgKyBzY2NhcHMKICAgICAKICAgICAgICAgICNtZWFucy9pbnRlcmNlcHRzCiAgICAgICAgICB2aXN1YWwgfiAxCiAgICAgICAgICB2ZXJiYWwgfiAxCiAgICAgICAgICBzcGVlZCB+IDEKICAgICAgICAgIHZpc3BlcmMgfiAwKjEKICAgICAgICAgIHBhcmNvbXAgfiAwKjEKICAgICAgICAgIGFkZGl0aW9uIH4gMCoxCiAgICAgICAgICcKCmZpdC4xYiA8LSBjZmEoY2ZhLjFiLCBkYXRhPWhzLCBtZWFuc3RydWN0dXJlPVRSVUUpCiNzdW1tYXJ5KGZpdC4xYiwgZml0Lm1lYXN1cmVzPVRSVUUsIHN0YW5kYXJkaXplZD1UUlVFLCByc3F1YXJlPVRSVUUpCmBgYAoKIVtdKGZpZ3VyZS9DRkFfbS5qcGcpe3dpZHRoPTQwJX0KCmBgYHtyfQpjZmEuMiA8LSAnI2ZhY3RvciBsb2FkaW5ncwogICAgICAgICAgdmlzdWFsID1+IHZpc3BlcmMgKyBjdWJlcyArIGxvemVuZ2VzICsgc2NjYXBzCiAgICAgICAgICB2ZXJiYWwgPX4gcGFyY29tcCArIHNlbmNvbXAgKyB3b3JkbWVhbgogICAgICAgICAgc3BlZWQgPX4gYWRkaXRpb24gKyBjb3VudGRvdCArIHNjY2FwcwogICAgICAgICAnCmZpdC4yIDwtIGNmYShjZmEuMiwgZGF0YT1ocywgbWVhbnN0cnVjdHVyZT1UUlVFLCBzdGQubHY9VFJVRSkKI3N1bW1hcnkoZml0LjIsIGZpdC5tZWFzdXJlcz1UUlVFLCBzdGFuZGFyZGl6ZWQ9VFJVRSwgcnNxdWFyZT1UUlVFKQoKbGF2VGVzdExSVChmaXQuMiwgZml0LjFhKQpgYGAKCmBgYHtyfQptb2RpbmRpY2VzKGZpdC4yLCBzb3J0Lj1UUlVFLCBtaW5pbXVtLnZhbHVlPTEwKQpgYGAKTm90ZSB0aGF0IG5vIGZ1cnRoZXIgY2hhbmdlcyBhcmUgc3VnZ2VzdGVkIGZvciB0aGUgbW9kZWwuCgohW10oZmlndXJlL0NGQV9tMi5qcGcpe3dpZHRoPTQwJX0KIApgYGB7cn0KY2ZhLjMgPC0gJyNmYWN0b3IgbG9hZGluZ3MKICAgICAgICAgIHZpc3VhbCA9fiB2aXNwZXJjICsgY3ViZXMgKyBsb3plbmdlcyAKICAgICAgICAgIHZlcmJhbCA9fiBwYXJjb21wICsgc2VuY29tcCArIHdvcmRtZWFuCiAgICAgICAgICBzcGVlZCA9fiBhZGRpdGlvbiArIGNvdW50ZG90ICsgc2NjYXBzCgogICAgICAgICAgI2NvdmFyaWFuY2VzCiAgICAgICAgICBhZGRpdGlvbiB+fiBjb3VudGRvdAogICAgICAgICAnCmZpdC4zIDwtIGNmYShjZmEuMywgZGF0YT1ocywgbWVhbnN0cnVjdHVyZT1UUlVFLCBzdGQubHY9VFJVRSkKI3N1bW1hcnkoZml0LjMsIGZpdC5tZWFzdXJlcz1UUlVFLCBzdGFuZGFyZGl6ZWQ9VFJVRSwgcnNxdWFyZT1UUlVFKQoKbGF2VGVzdExSVChmaXQuMywgZml0LjFhKQoKbW9kaW5kaWNlcyhmaXQuMywgc29ydC49VFJVRSwgbWluaW11bS52YWx1ZT0xMCkKYGBgCgpUaGlzIG1vZGVsIGlzIG5vdCBuZXN0ZWQgd2l0aCB0aGUgYWx0ZXJuYXRpdmUgbW9kaWZpZWQgbW9kZWw7IGhvd2V2ZXIsIHRoZSB0d28gbW9kZWxzIHByb3ZpZGUgbmVhcmx5IGVxdWl2YWxlbnQgZml0IChSTVNFQT0uMDY1IHZlcnN1cyAuMDY2LCBUTEk9Ljk0OCB2ZXJzdXMgLjk0NiwgZXRjLikuIFRodXMsIG1vZGVsIHNlbGVjdGlvbiBzaG91bGQgYmUgYmFzZWQgb24gd2hpY2ggbW9kaWZpY2F0aW9uIGlzIG1vc3QgcGxhdXNpYmxlLCBhbmQgdXBvbiB0aGUgaW50ZXJwcmV0YWJpbGl0eSBvZiBwYXJhbWV0ZXIgZXN0aW1hdGVzLgoKCgojIyMgMy4gTFNFTQoKMS4gdGhlIG1lYXN1cmVtZW50IG1vZGVsIGlzIGlkZW50aWNhbCB0byBDRkEgJHlfaT0gdiArXExhbWJkYVxldGFfaSArIFx2YXJlcHNpbG9uX2kkCjIuIHRoZSBzdHJ1Y3R1cmFsIG1vZGVsIGlzIHNpbWlsYXIgdG8gcGF0aCBhbmFseXNpcyAkXGV0YV9pPVxhbHBoYSArIEJcZXRhX2kgKyBcR2FtbWEgeF9pICsgXHpldGFfaSQKCk1lYXN1cmVtZW50IGludmFyaWFuY2UgKE1JKSByZWZlcnMgdG8gZXh0ZW50IHRvIHdoaWNoIHNhbWUgbWVhc3VyZW1lbnRzIGNvbmR1Y3RlZCB1bmRlciBkaWZmZXJlbnQgY29uZGl0aW9ucyB5aWVsZCBzYW1lIG1lYXN1cmVzIG9mIGF0dHJpYnV0ZXMgdW5kZXIgc3R1ZHkuIExvbmdpdHVkaW5hbCBpbnZhcmlhbmNlIGlzIHNhaWQgdG8gZXhpc3QgaWYgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgb2JzZXJ2ZWQgdmFyaWFibGVzIGRlcGVuZHMgb25seSBvbiB0aGUgbGV2ZWwgb2YgdGhlIGxhdGVudCB2YXJpYWJsZSBhbmQgbm90IGFsc28gb24gdGhlIHRpbWUgcG9pbnQgYXQgd2hpY2ggaXQgd2FzIG1lYXN1cmVkIGYoeXwkXGV0YSQsdCk9IGYoeXwkXGV0YSQpCgpUaGUgbGF0ZW50IGdyb3d0aCBjdXJ2ZSBpcyBjYXB0dXJpbmcgdGhlIGdyb3d0aCBhcyBhIGxhdGVudCBmYWN0b3IuIFRoZSBsYXRlbnQgY3VydmUgbW9kZWwgKExDTSkgaXMgZnVuZGFtZW50YWxseSBhIGhpZ2hseSByZXN0cmljdGVkIENGQSBtb2RlbC4gVGhlIHJlZHVjZWQtZm9ybSBlcXVhdGlvbiBpcyAkeV9pPSB2ICtcTGFtYmRhKFxhbHBoYStcemV0YV9pKSArIFx2YXJlcHNpbG9uX2kkCgohW10oZmlndXJlL0xDTTEuanBnKXt3aWR0aD01MCV9ICFbXShmaWd1cmUvTENNMi5qcGcpe3dpZHRoPTQwJX0KCgohW10oZmlndXJlL0xDTV9xLmpwZyl7d2lkdGg9NDAlfSAgIVtdKGZpZ3VyZS9MQ01fcC5qcGcpe3dpZHRoPTQwJX0KCioqVGltZSBpbnZhcmlhdGUgcHJlZGljdG9yLCBwcmVkaWN0IGJvdGggaW50ZXJjZXB0IGFuZCBzbG9wZSoqIGNoYW5nZSBzdHJ1Y3R1cmFsIG1vZGVsOiBhZGQgJFxHYW1tYSB4X2kkIGludG8gaXQuICR5X2k9IHYgK1xMYW1iZGEoXGFscGhhK1xHYW1tYSB4X2krXHpldGFfaSkgKyBcdmFyZXBzaWxvbl9pJAoKIVtdKGZpZ3VyZS9MQ00zLmpwZyl7d2lkdGg9NDAlfSAhW10oZmlndXJlL0xDTTQuanBnKXt3aWR0aD00MCV9CndoaWxlIHRpbWUtaW52YXJpYW50IGNvdmFyaWF0ZXMgYWRkIHByZWRpY3RvcnMgaW50byBzdHJ1Y3R1YWwgbW9kZWwsIHRpbWUtdmFyeWluZyBjb3ZhcmlhdGVzIGFkZCBwcmVkaWN0b3JzIGludG8gbWVhc3VyZW1lbnQgbW9kZWwuIGFkZCAkS3pfaSQuICR5X2k9IHYgK1xMYW1iZGEoXGFscGhhK1x6ZXRhX2kpICtLel9pKyBcdmFyZXBzaWxvbl9pJAoKIVtdKGZpZ3VyZS9MQ001LmpwZyl7d2lkdGg9NDAlfSAhW10oZmlndXJlL0xDTTYuanBnKXt3aWR0aD00MCV9CgojIyMgNC4gTUxNCiFbXShmaWd1cmUvbWl4ZWRfbW9kZWwuanBnKXt3aWR0aD0xMDAlfQpsbWUge25sbWV9IGZ1bmN0aW9uIGlzIGZsZXhpYmxlIGluIGF1dG9jb3JyZWxhdGlvbiBzdHJ1Y3R1cmUKYGBge3J9CnN1bW1hcnkobG1lKEFJUX4xICsgU1ogK1QxK1QyK1QzICsgU1o6VDEgKyBTWjpUMiArIFNaOlQzLCByYW5kb20gPSB+VDErVDJ8SUQsIGRhdGEgPSBjb2dfcHJlX2xvbmcsIG5hLmFjdGlvbiA9IG5hLm9taXQsCiAgICAgY29ycmVsYXRpb24gPSBjb3JDb21wU3ltbShmb3JtID0gIH4gMSB8IElEKSxtZXRob2QgPSAiTUwiLCAKICAgICBjb250cm9sID1saXN0KG1zTWF4SXRlciA9IDEwMDAsIG1zTWF4RXZhbCA9IDEwMDApKSkKYGBgCgpsbWVyIHtsbWU0fQpgYGB7cn0Kc3VtbWFyeShsbWVyKEFJUSB+IDEgKyBTWiArVDErVDIrVDMgKyBTWjpUMSArIFNaOlQyICsgU1o6VDMgKyAoMStUMStUMnxJRCksIGRhdGE9Y29nX2RhdF9sb25nKSkKYGBgCgo=